레지스터를 처음 공부하시면 아래의 내용이 잘 이해되지 않을 수 있습니다.
이런이런 레지스터가 있구나 하고 넘어가시고 어셈블리 코드를 보면서
각각의 레지스터 이용 방법에 대해 이해하시길 바랍니다.
휘발성 레지스터
몇몇 레지스터는 함수가 끝나면 그 값이 변합니다.
함수가 불려질때 휘발성 레지스터에 저장된 값은 함수가 보장하지 못하고,
비휘발성 레지스터에 저장된 값은 함수에 의해 그 값이 보존됩니다.
컴파일러에 따라서 어떤 레지스터를 휘발성 레지스터로 이용하는지가 달라집니다.
예 : 마이크로소프트 컴파일러
- 휘발성 레지스터 : ecx, edx
- 비휘발성 레지스터 : ebx, esi, edi, ebp
- Special: eax, esp
범용 레지스터
x86 아키텍쳐에서 사용되는 8개의 범용 레지스터에 대해 알아보겠습니다.
eax
eax는 32비트 범용 레지스터로, 함수의 리턴값을 저장하거나, 특정 계산에 이용됩니다.
그 값이 보존 되지 않으므로, 기술적으로는 휘발성 레지스터가 됩니다.
대신, eax의 값은 함수가 리턴되기 전에 리턴 값을 저장합니다.
또한 eax는 특수 레지스터로서 곱하기와 나누기 같은 계산을 합니다.
C 코드에서 함수 리턴 코드 입니다.
return 3; // 3을 리턴 합니다.
어셈블리에서 위와 동일한 함수 리턴 코드입니다.
mov eax, 3 ; eax를 3으로 세팅합니다. ret ; 함수를 리턴합니다.
ebx
ebx는 비휘발성 레지스터로, 특별히 정해진 역할은 없지만
계산의 속도를 높이기 위해 보통 0 과 같이 일반적인 값을 저장할 때 쓰입니다.
ecx
ecx 는 휘발성 범용 레지스터로 종종 루프 카운터나 함수의 파라미터로 사용됩니다.
"__fastcall" 호출 규약 함수는 ecx와 edx를 이용해 함수의 두 파라미터를 보내줍니다.
그리고 클래스의 맴버 함수를 부를때, 호출 규약에 상관없이 그 클래스의 포인터가 ecx에 저장됩니다.
또한 ecx는 rep 명령어 등에서 루프 카운터로 사용되며 0이 될 때 까지 계속 감소합니다.edx
edx 는 휘발성 범용 레지스터로 종종 함수의 파라미터로 사용됩니다.
ecx와 같이 ecx는 "__fastcall" 함수에서 사용됩니다.
ecx와 같이 ecx는 "__fastcall" 함수에서 사용됩니다.
esi
esi is a non-volatile general-purpose register that is often used as a pointer. Specifically, for "rep-" class instructions, which require a source and a destination for data, esi points to the "source". esi often stores data that is used throughout a function because it doesn't change.
edi
edi is a non-volatile general-purpose register that is often used as a pointer. It is similar to esi, except that it is generally used as a destination for data.
ebp
ebp is a non-volatile general-purpose register that has two distinct uses depending on compile settings: it is either the frame pointer or a general purpose register.
If compilation is not optimized, or code is written by hand, ebp keeps track of where the stack is at the beginning of a function (the stack will be explained in great detail in a later section). Because the stack changes throughout a function, having ebp set to the original value allows variables stored on the stack to be referenced easily. This will be explored in detail when the stack is explained.
If compilation is optimized, ebp is used as a general register for storing any kind of data, while calculations for the stack pointer are done based on the stack pointer moving (which gets confusing -- luckily, IDA automatically detects and corrects a moving stack pointer!)
esp
esp is a special register that stores a pointer to the top of the stack (the top is actually at a lower virtual address than the bottom as the stack grows downwards in memory towards the heap). Math is rarely done directly on esp, and the value of esp must be the same at the beginning and the end of each function. esp will be examined in much greater detail in a later section.
Special Purpose Registers
For special purpose and floating point registers not listed here, have a look at the Wikipedia Article or other reference sites.
eip
eip, or the instruction pointer, is a special-purpose register which stores a pointer to the address of the instruction that is currently executing. Making a jump is like adding to or subtracting from the instruction pointer.
After each instruction, a value equal to the size of the instruction is added to eip, which means that eip points at the machine code for the next instruction. This simple example shows the automatic addition to eip at every step:
eip+1 53 push ebx eip+4 8B 54 24 08 mov edx, [esp+arg_0] eip+2 31 DB xor ebx, ebx eip+2 89 D3 mov ebx, edx eip+3 8D 42 07 lea eax, [edx+7] .....
flags
In the flags register, each bit has a specific meaning and they are used to store meta-information about the results of previous operations. For example, whether the last calculation overflowed the register or whether the operands were equal. Our interest in the flags register is usually around the cmp and test operations which will commonly set or unset the zero, carry and overflow flags. These flags will then be tested by a conditional jump which may be controlling program flow or a loop.
16-bit and 8-bit Registers
In addition to the 8 32-bit registers available, there are also a number of 16-bit and 8-bit registers. The confusing thing about these registers it that they use the same storage space as the 32-bit registers. In other words, every 16-bit register is half of one of the 32-bit registers, so that changing the 16-bit also changes the 32-bit. Furthermore, the 8-bit registers are part of the 16-bit registers.
For example, eax is a 32-bit register. The lower half of eax is ax, a 16-bit register. ax is divided into two 8-bit registers, ah and al (a-high and a-low).
- There are 8 32-bit registers: eax, ebx, ecx, edx, esi, edi, ebp, esp.
- There are 8 16-bit registers: ax, bx, cx, dx, si, di, bp, sp.
- There are 8 8-bit registers: ah, al, bh, bl, ch, cl, dh, dl.
The relationships of these registers is shown in the table below:
32-bit | eax | ebx | ecx | edx | |||||||||||||||
16-bit | ax | bx | cx | dx | |||||||||||||||
8-bit | ah | al | bh | bl | ch | cl | dh | dl | |||||||||||
32-bit | esi | edi | ebp | esp | |||||||||||||||
16-bit | si | di | bp | sp |
Here are two examples:
eax | 0x12345678 |
ax | 0x5678 |
ah | 0x56 |
al | 0x78 |
ebx | 0x00000025 |
bx | 0x0025 |
bh | 0x00 |
bl | 0x25 |
64-bit Registers
A 64-bit register is made by concatenating a pair of 32-bit registers. This is shown by putting a colon between them.
The most common 64-bit register (used for operations such as division and multiplication) is edx:eax. This means that the 32-bits of edx are put in front of the 32-bits of eax, creating a double-long register, so to speak.
Here is a simple example:
edx | 0x11223344 |
eax | 0xaabbccdd |
edx:eax | 0x11223344aabbccdd |
참고 : http://www.skullsecurity.org/wiki/index.php/Main_Page
댓글 없음:
댓글 쓰기