임베디드/임베디드 레시피

stack : 함수를 불렀을때

러비코스믹 2024. 12. 6. 22:48

 

함수가 불렸을 때 일어나는 일.
 stack: history 기능, 즉, 선입후출 (가장 최근의 일을 알아 낼 수 있음)
 > 함수를 계속 불러 제껴도, 자기 자리로 돌아 올 수 있음

" 함수를 호출하게 되면 실행위치의 이동은 어떻게 되는가요?"
" 함수를 호출한 후, 전달하는 인자들은 어떻게 호출된 함수로 전달되는가요?"
" 호출된 함수가 실행을 끝내고 나면 어떻게 이전에 실행하던 위치로 복귀할 수 있는가요?"


 함수 call들
A()
{
............
B();
............ ●
}

B()
{
............
C();
............
}

C()
{
............
D();
............
}

D()
{
............
}

A()는 B()를 부르고, B()는 C()를 부르고, C()는 D()를 부르고,,
  > 결국 D()를 실행하고 나서 >  ● 지점으로 다시 돌아 와야함.

A()에서 B()를 부를 때,, stack > A()로 돌아갈 수 있는 표식을 넣어둠.
 + B()에서 C()를 부를 때, B()로 돌아갈 수 있는 표식을 stack에 쌓아 둠, 
 + C()에서 D()를 부를 때 C()로 돌아갈 표식을 stack에 쌓아둠


 

stack에 1, 2, 3 순서로 쌓아 둔 다음
   > 다시 거꾸로 갈 때 3, 2, 1 순서로 꺼내가면서 돌아감 

 stack에는 돌아갈 주소 + 전달인자들을 넣기도함

서브 루틴 호출시 수행되는 일
1. 전달 인자와 돌아갈 주소를 스택에 push하는일
2. 함수 호출 (즉, pc를 불리워진 함수의 주소로 jump시킴)
3. 지역변수에 대하여 스택에 저장공간을 할당하는 일
4. 호출된 함수를 수행하는일
5. stack에서 부터 할당된 지역변수 저장공간의 해제
6. 돌아갈 주소를 stack으로 부터 꺼내와 함수로부터의 복귀
7. 전달인자에 의해 사용되던 공간을 해제

. . . .
ex) 메모리 상에서 함수의 호출
main()이 sum()을 부름 > sum()이 display()를 호출

처음 main()영역 0xm1번지에서부터 opcode를 실행
 sum()을 호출하는 0xm6번지를 만남
  > 0xs1번지로 jump , stack : 돌아올 주소, 전달인자 등 ( 돌아오면 복구해야 할 것들 )
  > 또한 sum()을 실행하기 위해
        > sum()영역의 0xs1번지로 pc가 jump, 실행
        > display()를 호출하는 0xs4번지를 만남
              >  stack에 이것저것 집어 넣고, jump

 main()으로 돌아올 때는 반대의 경우

 각각의 함수들 = symbol >자기 고유의 물리적 주소를 가짐

 

 

 

 

 

 

ARM의 R14 - LR의 용법 

 

 

 ARM : 원래 Stack 관련한 CALL이나 RET 명령어를 지원 X,

   > Linked Register (R14)를 이용 > Branch하기 전에 돌아올 주소를 R14에 넣어둠

      > 복귀할 때 R14를 PC에 넣고 돌아옴

 

 

word a_fuct (word arg, word param)
{
   int localone, localtwo;
   word ret;

   localone = (int)(arg<<1);
   localtwo = (int)(param>>1);

   ret = b_funct ((word)localone, (word)localtwo);

   if (ret>100)
      message ("too big");
   else
      message ("appropriate");

   return ret;
}

 

>> asm 변환

 

addr/line__|code_____|label____|mnemonic________________|comment_________________ |word a_funct(word arg, word param)
3985|{
ST:1E6C1A10|B510 a_funct: push {r4,r14}
| int localone, localtwo;
| word ret;
|
3989| localone = (int)(arg<<1);
ST:1E6C1A12|0040 lsl r0,r0,#0x1 ; arg,arg,#1
3990| localtwo = (int)(param>>1);
ST:1E6C1A14|0849 lsr r1,r1,#0x1 ; param,param,#1
|
3992| ret = b_funct ((word)localone, (word)localtwo);
ST:1E6C1A16|B280 uxth r0,r0 ; localone,localone
ST:1E6C1A18|FFCEF7FF bl 0x1E6C19B8 ; b
ST:1E6C1A1C|4604 cpy r4,r0
|
3994| if (ret>100)
ST:1E6C1A1E|2C64 cmp r4,#0x64 ; ret,#100
ST:1E6C1A20|D903 bls 0x1E6C1A2A
3995| message ("too big");
ST:1E6C1A22|A078 add r0,pc,#0x1E0
ST:1E6C1A24|ED62F0AE blx 0x1E7704EC
ST:1E6C1A28|E002 b 0x1E6C1A30
| else
3997| message ("appropriate");
ST:1E6C1A2A|A078 add r0,pc,#0x1E0
ST:1E6C1A2C|ED5EF0AE blx 0x1E7704EC
|
3999| return ret;
ST:1E6C1A30|4620 cpy r0,r4 ; r0,ret
4000|}
ST:1E6C1A32|BD10 pop {r4,pc}
|

 

 

 

  a_funct()함수에 진입할 때 r4,r14 backup.// push {r4,r14} 

   >  컴파일러는 register를 backup 할 수 있도록 Assembly를 만듬

` 호출 받은 함수가 스크래치 레지스터 이외의 레지스터를 훼손하는 경우
    > 가령 함수 내에서 R4, R5를 훼손시키게 된다면, Stack을 이용해 이전 값을 저장하고 복구하여야함

마지막에  pop으로 r4를 복원 > 돌아갈 주소를 pc에 넣어줌

 a() 함수가 호출 > bl이라는 명령어로 호출 > Hardware적으로 자동으로 돌아갈 주소 값을 r14 (LR)에 넣음

>  호출된 함수에서는 r14값을 저장만 잘하면됨

//함수호출 : bl (branch with link)

 

BL function
...
...
function
...
...
MOV PC, LR


Return

 

 >  branch 다음다음 instruction으로 return하는 걸까?

질문)    PC : 항상 현재 instruction의 address보다 두 개 앞의 값을 갖고 있음

          >  call할 때 LR : branch 한 곳의 다음다음 instruction의 address가 들어감

why? ) branch 바로 다음 instruction으로 return되는 이유

>>  LR에 돌아갈 주소를 적어 넣을 때, BL 다음의 값을 LR에 자동으로 넣어줌  ( PC-4를 넣어주는 operation )

     돌아올 때는 branch 명령 바로 다음으로 돌아와야함

 

  branch 명령어 >>  branch 명령 바로 다음 값이 lr에 자동 저장!

퀴즈)
" 함수를 호출하게 되면 실행위치의 이동은 어떻게 되는가요?"
→ PC를 함수의 시작주소로 set // 함수 호출 : ( CPU 입장 ) 순차적으로 명령어 실행

        > 나 : 함수호출

        > 컴파일러 : 함수 시작 주소로 pc set


" 함수를 호출하여 전달하고자 하는 인자들은 어떻게 호출된 함수로 전달되는가요?"
→ AAPCS라는 걸 이용해서 정해진 Register에 값을 전달


" 호출된 함수가 실행을 끝내고 나면 어떻게 이전에 실행하던 위치로 복귀할 수 있는가요?" 

→ LR 이용! > bx r14

'임베디드 > 임베디드 레시피' 카테고리의 다른 글

Stack의 Size  (0) 2024.12.07
stack 메모리 dump  (0) 2024.12.07
stack initialization  (0) 2024.12.05
Stack , Heap  (1) 2024.12.05
struct , packed  (1) 2024.12.05