CPU는 mov eax, 0x100 같은 명령을 그대로 알아듣지 못합니다. 그래서 CPU가 알 수 있는 2진수 형태의 기계어로 변환해서 실행을 하게 됩니다.
오늘은 그 CPU가 실행하는 기계어를 사람이 알아 볼 수 있는 어셈블리 형태로 해석하는 방법을 알아보도록 하겠습니다.
먼저 인텔 CPU 매뉴얼이 필요합니다.(이건 인텔 웹사이트에서 받으세요, 이번 글에서는 Volume 2A: Instruction Set Reference, A-M"를 보면 됩니다.) 각 기계어가 의미하는 뜻을 알아보려면 매뉴얼을 봐야 합니다. 이 글에서는 mov 명령을 예로 들면서 설명하도록 하겠습니다.
mov 명령을 인텔 매뉴얼에서 찾아보면 다음과 같이 B8입니다.
mov 명령도 B8만 있는 것이 아니고 뒤에 오는 오퍼랜드의 종류에 따라서 여러가지가 있습니다. 이것은 인텔 매뉴얼 Instruction Set Reference의 mov 부분에 목록이 나와 있습니다. 그런데 mov 도표에 보면 B8+라고 되어 있는데 이+는 목적지 오퍼랜드의 종류에 따라 바뀐다는 것을 뜻합니다. 이 순서는 eax, ecx, edx, ebx, esp, ebp, esi, edi 순으로 지정되어 있는데, 따라서 mov eax는 B8, ecx는 B9, edx는 BA, ... edi는 BF가 됩니다.
그런데 mov 명령 중에서도 뒤에 오퍼랜드가 eax, ecx등 여러가지로 바뀌는데도 기계어는 똑같은 경우가 있습니다. 이것은 레지스터에 주소의 값을 대입하는 경우인데, ModR/M 바이트를 보고 판별합니다.
ModR/M 바이트는 3부분으로 구성되어 있는데, Mod 2비트, Reg/Opcode 3비트, R/M 3비트로 구성되어 있습니다. 이것은 인텔 매뉴얼 Instruction Set Reference의 앞부분에 보면 "32Bit Addressing Forms with the ModR/M Byte"라고 표 형태로 되어 있습니다.

위의 예에서 mov는 8B이고 eax, [edi] 부분은 07입니다. 이것은 ModR/M 표에서 찾으면 되는데, 첫번째 오퍼랜드는 세로줄이며, 두번째 오퍼랜드는 가로줄입니다. eax 줄에서 [edi]를 찾으면 07이 나옵니다. (이 경우에는 목적지가 레지스터기 때문에 mov가 8B입니다. 목적지가 메모리주소가 될 경우 mov는 89로 바뀌고, 표에서 찾을 때에도 첫번째 오퍼랜드는 가로줄이 되고 두번째 오퍼랜드는 세로줄이 됩니다. 그렇기 때문에 오퍼랜드의 종류와 방향에 따라 명령어의 기계어가 바뀌게 됩니다.)

이것 역시 mov는 8B이고 ebx, [ecx+] 부분은 59입니다. 4는 그 바로 뒤에 나오고 있습니다. 이걸 ModR/M 표에서 찾으면 ebx 줄에서 [ecx]+disp8에 있습니다. +disp8은 +4와 같은 오프셋을 뜻합니다. 8은 8비트 숫자를 나타냅니다. +disp32는 32비트 오프셋이겠죠.

이번에 것을 찾아보면 ecx 줄에 [eax+edx*2]라는 것이 없을 겁니다. 이런 경우는 [--][--]를 찾으면 됩니다. 이건 0C인데 eax+ebx*2는 어디에 있느냐? 50이 바로 eax+ebx*2를 뜻하고 있습니다. 이것은 ModR/M 표에서는 안나오고 ModR/M 바로 뒤에 보면 "32Bit Addressing Forms with the SIB Byte" 표에 나와 있습니다. eax 줄에서 edx*2를 찾으면 50이 나옵니다.

이 표를 찾는 것만 알고 있으면 어떤 기계어가 나와도 인텔 매뉴얼에서 다 찾을 수 있을 것입니다.


댓글을 달아 주세요
깔끔하게 잘 설명이 된 자료입니다. 제 블로그에 퍼가도 되나요? ^^
Blog의 글들은 링크만 허용합니다.
역어셈블.. 말은 간단한데, 엄청 어려운 일이지요.. ^^;; 몇 줄 하다 보면, CPU 인스트럭션 메뉴얼을 외우게 될 것 같아요..
요새는 인텔 계열 MCU하고, 프리스케일 계열 MCU를 왔다리 갔다리 하니까, 리틀 엔디안/빅 엔디안 맨날 햇갈려요.. ^^