하드웨어의 프로시저 지원

한포도·2024년 4월 5일
0

Compter Architecture

목록 보기
8/8
post-custom-banner

프로시저 (procedure)

-프로시저란 제공되는 인수(argument) 따라서 특정 작업을 수행하는 서브루틴이다
-프로시저나 함수는 이해하기 쉽고 재사용이 가능하도록 프로그램을 구조화하는 방법 중 하나
-프로그래머가 한번에 한 부분씩 집중할 수 있게함 (추상화)
-인수 (argument)는 프로그램의 다른부분과 프로시저 사이의 인터페이스 역할 : 값을 보내고 결과를 받아옴

간단하게 말해서 HLL에서 함수가 있다면 어떻게 컴파일하고 어떻게 하드웨어에서 실행하는가? 를 구조화 한다.

📞프로시저 호출

  • 프로시저를 호출하는데는 몇가지 스텝이 필요하다.
  • 매개변수를 레지스터로 넘긴다
  • 프로시저로 제어를 넘긴다
  • 프로시저가 필요로 하는 메모리 자원을 획득한다
  • 필요한 작업을 수행한다
  • 호출한 프로그램을 위해서 레지스터에 결과를 저장한다
  • 원래 위치로 제어를 돌려준다

2번째 순서에서 명령어가 실행되는 시점에 따라서 다음 실행의 명령어를 프로시저로 브랜치한다.
4~6번까지는 메모리를 확보하고 작업을 수행하고 레지스터에 결과를 저장한후 프로시저 내부의 명령어를 호출한 프로그램 위치로 넘겨준다.

🗣️ 레지스터 소개

앞으로 이 부분은 계속해서 왔다갔다 하며 보게 될것이므로 잘 기억해놓자.
$a0 – $a3: 인수 레지스터 (reg’s 4 – 7)

$v0, $v1 : 결과 레지스터 (reg’s 2 and 3)

$t0 – $t9: 보존하지 않는 변수 레지스터 / 템포럴리

  • 호출된 프로시저에 의해서 덮어씌어질 수 있음

$s0 – $s7: 보존되야 하는 변수 레지스터 / 세이브 중요한 데이터

  • 호출된 프로시저는 원래 값을 따로 저장하여 복원해야함.
  • 왜냐면 본래 값의 담긴 레지스터를 사용한다면 이전 값을 기억해놔야 다음 연산에 쓰기 때문에

$gp : 정적 데이터를 위한 글로벌 포인터 (reg 28)
$sp : 스택 포인터 (reg 29) - 스택 메모리의 주소가 됨
$fp : 프레임 포인터 (reg 30)
$ra : 복귀 주소, return address (reg 31)
PC(program counter) : 프로세서가 실행할 명령어의 주소를 저장하는 레지스터, 32개의 레지스터와 별개다. 한마디로 CPU가 실행할 명령어들을 순차적으로 저장하는 레지스터다.

✍️ 프로시저 호출 명령어

jal 이라고 하며, 명령어의 실행은 두가지로 나눌수 있다.
jal ProcedureLabel 처럼 사용한다.

LINK : 여러가지 명령어를 순차적으로 실행한뒤 명렁어 다음의 주소(PC+4) 로 복귀 하기 위해 주소를 $ra 에 저장한다. 명령어는 4바이트기 때문에 +4를 해주는것.
JUMP : 해당 레이블로 이동한다.

↩️프로시저 복귀 : jump reigster

jr 이라고 한다. jr $ra로 사용하며, 피호출 프로그램으로부터 호출프로그램으로 복귀한다. 프로시저로 넘어간 제어가 다시 본 프로그램으로 돌아온다.

리프 프로시저 예시 (Leaf Procedure Example)

리프 프로시저는 어떤 프로시저나 함수에서 다른 서브루틴이나 함수를 호출하지 않는 프로시저다. 즉, 리프 프로시저는 자신만의 작업을 수행하고 반환한다. 콜백함수와 비슷한 개념이라고 생각해도 좋다.

C code:

	int leaf_example (int g, h, i, j){
    
    int f;
    f = (g + h) - (i + j);
    return f;
    
    }

1. g, …, j in $a0, …, $a3

  • 매개변수를 레지스터로 넘기는 과정
  • 이 과정은 호출 프로그램이 실행한다.

2. f in $s0

  • 따라서 $s0의 원래 값은 따로 저장 해 놓아야 함
  • 레지스터 스필링 (원래 값은 프로시저 실행 중에 쓰지 않음)

3. 결과는 $v0에 저장

MIPS code:

(프로시저 호출)
jal leaf_example  ($ra에는 add $s0, $v0, $s0의 주소가 저장)
add $s0, $v0, $s0 ($s0를 따로 저장 해 놓아야 하는 이유)
-----------------------------------------------------
-----------------------------------------------------

leaf_example:   addi $sp, $sp, -4        #이후에 배움
                sw   $s0, 0($sp)         #이후에 배움
                add  $t0, $a0, $a1              
                add  $t1, $a2, $a3              
                sub  $s0, $t0, $t1              
                add  $v0, $s0, $zero             
                lw   $s0, 0($sp)              
                addi $sp, $sp, 4              
                jr   $ra              #PC에 $ra가 저장

논 리프 프로시저 (Non-Leaf Procedures)

논 리프 프로시저(Non-leaf Procedure)란 프로시저(함수)가 다른 프로시저를 호출한 후에 반환(return)하는 프로시저다. 다시 말해, 해당 프로시저가 호출한 다른 프로시저 내부에서 처리가 이루어지고, 해당 프로시저는 호출된 프로시저가 반환한 후에야 반환된다.
논 리프 프로시저는 호출한 프로시저의 제어를 반환하는 것이 아니라 다른 프로시저를 호출하여 작업을 위임하고, 그 작업이 끝난 후에 자신의 작업을 계속하는 경우에 사용된다. 이러한 상황에서는 호출한 프로시저의 상태를 보존하고 관리해야 하므로, 보존해야 할 레지스터나 기타 상태를 적절히 관리해야 한다.

ex)
- 인수 3을 레지스터에 저장하고 프로시저 A를 호출
	(jal A, $ra에 A의 복귀주소 저장, $a0에 인수값 3이 저장)
- 프로시저 A가 인수값 7을 가지고 프로시저 B를 호출 
(jal B, $ra에 B의 복귀주소 저장, $a0에 인수값 7이 저장)
-> $a0의 3이 사라지고 복귀주소가 충돌이 나게 된다

그럼 어캄????? 망햇네 망햇서

자 만약에 a1레지스터를 사용해야하는데 이미 1이라는 값이 있다고 가정하자. 그럼 호출 프로그램은 호출이 끝난뒤에 복구해야 할 레지스터를 따로 저장해 두어야 한다. 다른곳에 저장해뒀다가 프로시저가 끝나면 다시 호출하면 되기 떄문이다. 그럼 호출자는 인수나 임시레지스터중 고유값을 저장할 필요가 있는 레지스터를 따로 저장해두고 피호출자 혹은 callee는 호출된 시점에서의 복귀할 주소가 담긴 레지스터와 피호출 프로그램의 결과인 저장 레지스터를 저장해놓는다.

  • 간단하게 말해서 호출,피호출 프로그램은 보존되어야 할 모든 값을 메모리에 저장/적재를 한다.
profile
응애 개발맨
post-custom-banner

0개의 댓글