함수 스택에서, block안의 정의에 대한 궁금증

lacovnk의 이미지

보통 함수가 call하면, 당시 stack은 이렇게 구성이 되는데

-----------
arg
----------- <- fp
saved register
-----------
local variable
----------- <- sp

다음과 같은 함수에서, in-block의 int c는 어떻게 처리해야 하나요?

int foo(int a, int b)
{
   int d;
//blabla
   { // in-block
      int c;
      blabla;
   }
}

block을 들어가서 선언을 만나면, sp를 옮겨버리고 그 사이를 int c 저장하는데 쓰면 되나요?

-----------
arg
----------- <- fp
saved register
-----------
int d
-----------
int c
----------- <- sp

그리고 block 나갈때 다시 sp를 줄여버리고...

근데 이렇게 하면 기존에 d녀석을 접근하려고 할 때, block 내에서 접근할 경우와, block 밖에서 접근 할때 sp와의 offset이 변하는데, 불편한 것 같은데..

갑자기 궁금해졌습니다.
어차피 saved register의 크기는 알고 있을 텐데, 왜 sp의 offset을 쓰지요? 그냥 fp의 offset을 쓰면 안될까요? 음음.

익명 사용자의 이미지

Quote:
-----------
arg
----------- <- fp
saved register
-----------
local variable
----------- <- sp

int foo(int a, int b)
{
   int d;
//blabla
   { // in-block
      int c;
      blabla;
   }
}

코드를 보면 C나.. 그런 종류 언어 같은데... 음.. 이해가 잘 안되네요.
왜 보통 함수 호출할때.. 스택이 위의 모양이 되죠?
스택 메모리 얘기아닌가요? fp, sp는 뭘뜻하죠?
함수포인터 스택포인터 인가요?
보통 스택메모리 표현하는 레지스터로는 bp,sp가 쓰이지 않나요..?
제가아는 것과 차이가 있는거 같아서 질문드립니다.

한가지 더... 보통함수가 호출될때마다 레지스터가 저장된다는 것은 납득이 안되네요..

Fe.head의 이미지

원소스

void foo_sub(int ar1, int ar2)
{
    int foo_sub_1;
    int foo_sub_2;

    foo_sub_1 = 10;
    foo_sub_2 = ar2;

    {
        int block1;
        int block2;
        block1 = foo_sub_1;
        block2 = 0;
    }
}

어셈블리 소스

void foo_sub(int ar1, int ar2)
{
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
/*
스택에 지역 변수 16Byte 할당 
foo_sub 함수의 foo_sub_1, foo_sub_2, 아래 블럭 변수들 block_1, block_2
  : sizeof(int) * 변수개수(4) = 16
*/
   3:   83 ec 10                sub    $0x10,%esp 
    int foo_sub_1;
    int foo_sub_2;

    foo_sub_1 = 10;
   6:   c7 45 f0 0a 00 00 00    movl   $0xa,-16(%ebp)
    foo_sub_2 = ar2;
   d:   8b 45 0c                mov    0xc(%ebp),%eax
  10:   89 45 f4                mov    %eax,-12(%ebp)

    {
        int block1;
        int block2;
        block1 = foo_sub_1;
  13:   8b 45 f0                mov    -16(%ebp),%eax
  16:   89 45 f8                mov    %eax,-8(%ebp)
        block2 = 0;
  19:   c7 45 fc 00 00 00 00    movl   $0x0,-4(%ebp)
    }
}
  20:   c9                      leave
  21:   c3                      ret

으흠. gcc에서는 블럭 스택이 안생기는군요.

고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"

lacovnk의 이미지

Anonymous wrote:
Quote:
-----------
arg
----------- <- fp
saved register
-----------
local variable
----------- <- sp

int foo(int a, int b)
{
   int d;
//blabla
   { // in-block
      int c;
      blabla;
   }
}

코드를 보면 C나.. 그런 종류 언어 같은데... 음.. 이해가 잘 안되네요.
왜 보통 함수 호출할때.. 스택이 위의 모양이 되죠?
스택 메모리 얘기아닌가요? fp, sp는 뭘뜻하죠?
함수포인터 스택포인터 인가요?
보통 스택메모리 표현하는 레지스터로는 bp,sp가 쓰이지 않나요..?
제가아는 것과 차이가 있는거 같아서 질문드립니다.

한가지 더... 보통함수가 호출될때마다 레지스터가 저장된다는 것은 납득이 안되네요..

아, 지금 target이 mips인데, 그 레퍼런스 pdf에는 그렇게 나와있습니다;;

http://www.cs.wisc.edu/~larus/HP_AppA.pdf

음. 1-pass로 만들려면, 함수 처음 시작할 때에 블럭의 유무를 알 수 없기 때문에 어쩔수 없이 block이 생길 때 처리를 해줘야 할 것 같습니다.

음. 그리고 mips의 call convention에서는 callee가 caller의 register 중 보존되어야 할 것을 알아서 저장해줘야 합니다

Quote:
Save caller-saved registers. The called procedure can use these registers
($a0–$a3 and $t0–$t9) without first saving their value. If the caller expects to use one of these registers after a call, it must save its value before the call.

음.. -o-