============================== Assembly =================================
7 => 0x0000000000400548 <+20> : callq 0x400526 <my_func> 일 때,
call : 함수 호출시 사용하는 니모닉(mnemonic)
call = push + jmp
push 는 복귀 주소를 스택에 저장함
jmp 는 call 뒤에 오는 주소값으로 이동시킴
<call 전>
(gdb) p $rsp
$1 = 0x7fffffffdd20
<call 이후>
(gdb) p $rsp
$2 = 0x7fffffffdd18 // 주소가 바뀌어 있다 !! 8Byte 할당 받음..
(gdb) x $rsp
$3 = ffdd18 : 0x0040054d // 들어있는 값을 확인 - 함수가 끝난 후, 복귀할주소 저장되어 있음
============================== Computer =================================
7. callq 니모닉 처리
0x7fffffffdd18 |
| 0x7fffffffdd30 | 숫자 '3' | 숫자 '3' | ||||||
rsp 레지스터 |
| rbp 레지스터 | eax 레지스터 | edi 레지스터 |
Stack | 메모리 주소 | ||
| 0x00400570 |
| 0x7fffffffdd38 0x7fffffffdd30 |
숫자 3 | | 0x7fffffffdd28 | |
|
| 0x7fffffffdd20 | |
0x0040054d | <rsp | 0x7fffffffdd18 | |
0x00400570 | <(-0x8(%rsp)) | 0x7fffffffdd10 |
함수가 끝난 후 복귀해야 할 주소 : 0x0040054d 는 현재, rsp가 가리키는 스택에 들어있음
함수가 끝나면 Jump니모닉을 실행할 터이고.. 그럼 저 주소로 Jump 함..
그런데.. 가만보니.. my_func 함수가 실행되는 동시에.. 스택프레임이 다시 생성되고 있음 !!
(gdb) x $rsp -0x8
$4 = ffdd10 : 0x00400570
============================ 함수 안으로 들어가서.. ===========================
int my_func(int n){ return n* 2; } |
|
0x0000000000400526 <+0> : push %rbp 0x0000000000400527 <+1> : mov %rsp, %rbp 0x000000000040052a <+4> : mov %edi, -0x4(%rbp) 0x000000000040052d <+7> : mov -0x4(%rbp), %eax 0x0000000000400530 <+10> : add %eax, %eax 0x0000000000400532 <+12> : pop %rbp 0x0000000000400533 <+13> : retq |
============================== Assembly =================================
8 => 0x0000000000400526 <+0> : push %rbp 는, 위에서 callq 호출시 실행되었고
(gdb) p $rsp
$4 = 0x7fffffffdd10 // 스택 프레임 생성 : 공간할당 -> rbp 주소 따라가면 있는 데이터 밀어넣기
============================== Assembly =================================
9 => 0x0000000000400527 <+1> : mov %rsp, %rbp 일 때,
rsp의 값을 rbp에 넣어라
(gdb) p $rsp
$5 = 0x7fffffffdd10 // 8Byte 공간할당 됨, 돌아갈 주소의 포인터를 갖고 있음
(gdb) p $rbp
$6 = 0x7fffffffdd10 // rsp == rbp , 동일한 상황이 됨
(gdb) x $rsp
0x7ffdd10 : 0xffdd30 // 이전 rbp 위치를 가리키고 있다 -ㅁ- ;;
============================== Computer =================================
9. 스택프레임 재생성 - rbp 재설정
0x7fffffffdd10 |
| 0x7fffffffdd10 | 숫자 '3' | 숫자 '3' | ||||||
rsp 레지스터 |
| rbp 레지스터 | eax 레지스터 | edi 레지스터 |
Stack | 메모리 주소 | ||
이전 rbp위치> | 0x00400570 |
| 0x7fffffffdd38 0x7fffffffdd30 |
숫자 3 | | 0x7fffffffdd28 | |
| 0x7fffffffdd20 | ||
0x0040054d | | 0x7fffffffdd18 | |
| 0x00400570 | | 0x7fffffffdd10 |
============================== Assembly =================================
10 => 0x000000000040052a <+4> : mov %edi, -0x4(%rbp) 일 때,
edi 의 값을 rbp-0x4 위치에 넣어라
(gdb) p $rsp
$7 = 0x7fffffffdd10
(gdb) p $rbp
$8 = 0x7fffffffdd10
(gdb) x $rbp -0x4
0x7ffdd0c : 0x00000003 // edi 레지스터의 값을 스택에 넣었음을 확인
============================== Computer =================================
10. (의미없는 수행) edi 레지스터의 데이터를 스택에 넣어라
0x7fffffffdd10 |
| 0x7fffffffdd10 | 숫자 '3' | 숫자 '3' | ||||||
rsp 레지스터 |
| rbp 레지스터 | eax 레지스터 | edi 레지스터 |
Stack | 메모리 주소 | ||
0x00400570 |
| 0x7fffffffdd38 0x7fffffffdd30 | |
숫자 3 | | 0x7fffffffdd28 | |
| 0x7fffffffdd20 | ||
0x0040054d | | 0x7fffffffdd18 | |
| 0x00400570 | | 0x7fffffffdd10 |
| 숫자 '3' |
|
============================== Assembly =================================
11 => 0x000000000040052d <+7> : mov -0x4(%rbp), %eax 일 때,
rbp-0x4 의 값을 eax 레지스터에 넣어라
(gdb) p $eax
$9 = 3 // eax 레지스터에 이미 3 들어 있는데.. 또 3을 넣다니.. 의미없는 수행과정
============================== Computer =================================
11. (의미없는 수행) rbp-0x4의 값을 eax 레지스터에 넣어라
0x7fffffffdd10 |
| 0x7fffffffdd10 | 숫자 '3' | 숫자 '3' | ||||||
rsp 레지스터 |
| rbp 레지스터 | eax 레지스터 | edi 레지스터 |
Stack | 메모리 주소 | ||
0x00400570 |
| 0x7fffffffdd38 0x7fffffffdd30 | |
숫자 3 | | 0x7fffffffdd28 | |
| 0x7fffffffdd20 | ||
0x0040054d | | 0x7fffffffdd18 | |
| 0x00400570 | | 0x7fffffffdd10 |
-0x4(%rbp)> | 숫자 '3' |
0x7fffffffdd0c |
============================== Assembly =================================
12 => 0x0000000000400530 <+10> : add %eax, %eax 일 때,
eax += eax
(gdb) p $eax
$10 = 6 // 3 += 3 이므로, eax 레지스터의 값이 6으로 갱신됨
============================== Computer =================================
12. 3 더하기 3은~?
0x7fffffffdd10 |
| 0x7fffffffdd10 | 숫자 '6' | 숫자 '3' | ||||||
rsp 레지스터 |
| rbp 레지스터 | eax 레지스터 | edi 레지스터 |
============================== Assembly =================================
13 => 0x0000000000400532 <+12> : pop %rbp 일 때,
1. rbp 는 : 이전 rbp위치 에 담겨있는 정보 - 돌아갈 주소로 감
2. rsp 는 : +0x8 됨.. 할당 전의 주소로 복귀
(gdb) p $rbp
$11 = 0x7fffffffdd30
(gdb) p $rsp
$12 = 0x7fffffffdd18
(gdb) x $rbp
0x7fffffffdd30 = 0x00400570
(gdb) x $rsp
0x7fffffffdd18 = 0x0040054d
(gdb) p $rip
$12 = 0x400533 <my_func+13>
============================== Computer =================================
13. pop 니모닉 실행
0x7fffffffdd18 |
| 0x7fffffffdd30 | 숫자 '6' | 숫자 '3' | ||||||
rsp 레지스터 |
| rbp 레지스터 | eax 레지스터 | edi 레지스터 |
Stack | 메모리 주소 | ||
rbp> | 0x00400570 |
| 0x7fffffffdd38 0x7fffffffdd30 |
숫자 3 | | 0x7fffffffdd28 | |
| 0x7fffffffdd20 | ||
0x0040054d | | 0x7fffffffdd18 | |
| 0x00400570 | | 0x7fffffffdd10 |
-0x4(%rbp)> | 숫자 '3' |
0x7fffffffdd0c |
============================== Assembly =================================
14 => 0x0000000000400533 <+13> : retq 시전 과 동시에, <my_func>함수를 빠져나옴
0x000000000040054d <+25> 할 차례라고 가리키고 있음
============================== Computer =================================
14.
0x7fffffffdd18 |
| 0x7fffffffdd30 | 숫자 '6' | 숫자 '3' | ||||||
rsp 레지스터 |
| rbp 레지스터 | eax 레지스터 | edi 레지스터 |
Stack | 메모리 주소 | ||
| 0x00400570 |
| 0x7fffffffdd38 0x7fffffffdd30 |
숫자 3 | | 0x7fffffffdd28 | |
| 0x7fffffffdd20 | ||
0x0040054d | <rsp | 0x7fffffffdd18 | |
|
이 정도만 보아도.. 그동안 배운 자료구조, 운영체제, C언어, 어셈블리, 컴퓨터구조.. 등 많은 과목이 스쳐지나가면서
퍼즐이 맞춰지듯 이해가 된다.. 신기하다..