※ 질문/내용오류/공유할 내용이 있다면 jinkilee73@gmail.com으로 메일 주세요 :-)
이전의 포스팅에서 어셈블리언어의 명령어들이 어떤 것들이 있는지 살펴보았다. 물론 그 외에도 무지하게 많은 명령어들이 있으나 다른 명령어들에 대해서는 앞으로 나올때마다 소개하는 식으로 하겠다.
자 그러면 하나의 예제를 통해서 이해해보자.
이와 같은 C 파일이 있다고 했을 때, 이것을 어셈블리 언어로 바꿔보자.
보아하니 .cfi_endproc 등등 처음 본 것들도 막 보인다. 깔끔하게 무시해주자. 저것은 나도 모르겠다. 하나 중요한 것은 저걸 지워도 프로그램은 잘 돌아가더라는 것이다. 저것이 무엇인지는 나중에 같이 공부해보자.
또 하나 우리가 스킵하고 넘어가야 하는 부분이 있다. 위의 세 줄과 밑의 두 줄이다.
pushl %ebp
movl %esp, %ebp
subl $16, %esp
leave
ret
이 부분은 나중에 procedure call을 공부할 때 공부하는 부분이다. 지금은 그냥 한 함수의 시작과 끝을 표시해주는 것이라고만 생각하자.
## movl 8(%ebp), %edx
M[ %ebp + 8 ] 값을 %edx에 복사하라는 뜻이다. 그렇다면 %ebp에는 무엇이며 그것의 8칸 위에는 뭐가 있냐? %ebp 란 스택 프레임만을 가리키는 특별한 목적을 지닌 레지스터이다. 말이 어려워진다. 그냥 %ebp라는 어떤 기준이 되는 것이 있다고만 알자. 나중에 전부 Procedure Call에서 자세하게 다룰 것이다. 그러면 %ebp + 8에는 뭐가 있냐? swap(int* xp, int y)함수의 첫번째 파라미터 즉, xp의 값이 들어온다. xp는 포인터 값이므로 결국 M[ %ebp + 8 ]가 가리키는 값은 어떤 값을 가리키고 있는 주소값이 되겠다. 아래의 그림과 같다.
아직은 %ebp가 뭔지는 잘 모르겠지만 그 값이 아무튼 0x8048038이다.
movl 8(%ebp), %edx 명령어는 %ebp + 8 인 0x8048040의 값, 즉 0x8048010을 %edx에 저장하라는 뜻이다. 따라서 다음의 결과가 된다. 결국 xp라는 메모리 값을 레지스터에 저장해둔 것이다.
## movl (%edx), %eax
xp가 가리키는 값을 255(0xFF)라고 가정하고 이야기 해보자.
이 명령어는 위의 명령어보다 조금 더 이해하기가 쉬울 거라고 생각한다 %edx가 가리키는 값인(0x000000FF)를 %eax에 저장하라는 뜻이다. 왜 %edx가 가리키는 값이 0x00이 아니고 0x000000FF인가? int 형은 몇 바이트인가? 4바이트이다. 그런데 위의 메모리 한 칸은 1바이트이다. 따라서 0x8048010에서부터 0x804800D까지 네 칸을 할당해서 사용해야한다.
이 명령어는 결국 xp가 가리키고 있는 255를 레지스터에 저장해두는 것과 같은 역할을 한다. 결과는 다음과 같아진다.
여기서 한가지 중요한 이야기를 하고 가자. 함수의 return 값은 항상 %eax에 저장된다. 위의 C코드를 다시 한번 보면, 이 함수의 return 값은 애초에 xp가 가리키고 있었던 정수(0xFF)이다. 따라서 0xFF가 %eax에 저장되는 것이다.
## movl 12(%ebp), %ecx
(swap 함수를 호출할 때 두번째 파라미터인 y에는 0이 있다고 가정하자.)
위에서 M[ %ebp + 8 ]에는 swap(int* xp, int y)의 첫번째 파라미터가 들어있다고 했다. 같은 원리로 두번째 파라미터는 12(%ebp)에 존재하게 된다. 그렇다. 함수의 파라미터들은 항상 %ebp값을 기준으로 +8칸 부터 그 위로 쭉쭉 쌓여나간다. +4칸에는 뭐가 있는가? 그것은 나중에 자세하게 이야기할 것이니 지금은 신경쓰지 말도록 하자.
아무튼 이 명령어의 결과는 아래와 같은 그림이 될 것이다.
M[ %ebp + 12 ]의 값을 %ecx 에 복사하는 것이다. 왜 0x8048044 로부터 네 칸이냐고? 위에서 다 설명했다.-_- 결국 이 명령어는 int y 값을 레지스터에 저장하는 명령어이다.
## movl %ecx, (%edx)
이 명령어는 간단하다. %ecx값 0x00000000를 %edx가 가리키는 값에 집어넣는 것이다. 따라서 아래와 같은 결과가 나온다.
결국 이 명령어는 xp가 가리키는 값을 y값으로 변경시키는 것이다.
정리해보면 다음과 같다.
간단하게 예제를 통해 어셈블리 명령어를 이해해봤으니 다음 포스팅에서는 중요한 아주 중요한 push 명령어와 pop 명령어에 대해서 이야기 해보도록 하자. 이는 procedure call을 이해하는데 있어서 매우 중요한 사전 지식이 된다.
※ 앞으로 메모리칸을 그릴 때는 1바이트 단위로 자세하게 그리지 않고 4바이트 단위로 끊어서 그릴 생각이다. 혼동하지 않길 바란다. 그것이 조금 더 이해하기 쉬울 것이라고 믿는다.
'System Programming' 카테고리의 다른 글
[SP] Conditional Jump (Basic) (0) | 2013.05.14 |
---|---|
[SP] Procedure Call (0) | 2013.05.04 |
[SP] Assembly Language (1) | 2013.04.30 |
[SP] Assembly Language Basic (0) | 2013.04.29 |
[SP] Purpose for Virtual Memory (0) | 2013.04.29 |