어셈블리 명령어
INC : 피연산자에 1을 더한다
결과에 따라 ZF, OF가 세트될 수 있다.
DEC : 피연산자에 1을 뺀다
결과에 따라 ZF, OF, CF가 세트될 수 있다.
ADD : Destination 에 Source 값을 더해서 Destination에 저장하는 명령이다
ex) ADD destination , source
결과에 따라 ZF, OF, CF가 세트될 수 있다.
SUB : Destination 에 Source의 값을 빼서 Destination에 저장하는 명령이다.
ex) SUB destination, source
결과에 따라 ZF, OF, CF가 세트될 수 있다.
MUL : 부호 없는 al, ax eax의 값을 피연사자와 곱한다.
피연산자가 8비트이면 al과 곱해서 ax에 저장되고 16비트이면 ax와 곱하고 dx:ax에 저장된다.
결과에 따라 OF, ZF가 세트될 수 있다.
IMUL : 부호 있는 al, ax, eax의 값을 피연산자와 곱한다.
ex) IMUL r/m
단일 피연산자일 경우 피연산자를 al, ax eax에 곱한다.
ex) IMUL destination, value
value를 al, ax, eax와 곱해서 destination에 저장한다.
ec) IMUL destination, value, value
value끼리 곱해서 destination에 저장한다.
연산결과가 destination 레지스터의 크기보다 크다면 OF, CF가 세트된다.
DIV : 8, 16, 32비트 부호없는 정수의 나눗셈을 수행한다.
결과에 따라 CF, OF, ZF가 세트될 수 있다.
MOV : Source에서 Destination으로 데이터를 복사한다.
ex) MOV Destination, Source
ESI혹은 SI레지스터에 의해 지정된 메모리 주소의 내용을 EDI, DI레지스터에 의해 지정되는 메모리 주소로 복사한다.
이때 피연산자 타입은 레지스터와 메모리 모두 해당된다.
MOV EAX, [EBP]
로 중괄호 표현이 있는경우 EBP가 가리키는 주소에서 값을 가져와 EAX에 대입한다.
MOV EAX, [EBP + 10]
이면 EBP의 주소에서 10만큼 더한 주소지의 값을 가져와 EAX에 대입한다.
MOVS : Source에서 Destination으로 데이터를 복사한다.
ex) MOV Destination, Source
ESI혹은 SI레지스터에 의해 지정된 메모리 주소의 내용을 EDI, DI레지스터에 의해 지정되는 메모리 주소로 복사한다.
이때 피연산자 타입은 레지스터만 가능하다.
작은데이터 단위를 크게 확장한다.
MOVSB : BYTE단위로 복사한다.
MOVSW : WORD단위로 복사한다.
MOVSD : DWORD단위로 복사한다.
방향플래그(DF)가 1로 세트되어 있으면 ESI와 EDI는 복사시에 감소하게된다.
DF가 0으로 세트되어있으면 ESI와 EDI는 복사시에 증가하게 된다.
MOVSX : BYTE나 WORD크기의 피연산자를 WORD나 DWORD크기로 확장하고 부호는 그대로 유지한다.
MOVZX : BYTE나 WORD크기의 피연산자를 WORD나 DWORD크기로 확장하고 남은 비트는 0으로 채운다.
INT : 소프트웨어 인터럽트를 발생시켜 운영체제의 서브루틴을 호출한다.
※서브루틴 >> 어떤 특정한 기능을 하는 부 프로그램(함수)
AND : Destination 과 Source 피연산자의 각 비트가 AND연산 된다.
ex) Destination : 10011100
Source : 11001010
>> 10001000
OF, CF가 0으로 세트되고 결과에따라서 ZF가 1로 세트될 수 있다.
OR : Destination 과 Source 피연산자의 각 비트가 OR연산 된다.
ex) Destination : 10011100
Soruce : 11001010
>> 11011110
OF, CF가 0으로 세트되고 결과에 따라서 ZF가 1로 세트될 수 있다.
XOR : Destination 과 Source 피연산자의 각 비트가 XOR연산 된다.
ex) Destination : 10011100
Source : 11001010
>> 01010110
OF, CF가 0으로 세트되고 결과에 따라 ZF가 1로 세트될 수 있다.
피연산자가 같다면 결과는 항상 0이다.
레지스터를 0으로 초기화 시킬때 MOV명령어를 사용하기보다는 XOR reg, reg으로 많이 사용한다.
TEST : 두 피연산자를 AND연산을 수행하여 플래그 레지스터에 여향을 주지만 결과 값은 저장하지 않는다
OF, CF는 항상 0으로 세트되고 TEST연산 결과값이 0이면 ZF가 1 아니면 0으로 세트된다.
STC : CF를 1로 세트한다
CLC : CF를 0으로 세트한다.
STD : DF를 1로 세트한다.
CLD : DF를 0으로 세트한다.
STI : IF를 1으로 세트한다.
CLI : IF를 0으로 세트한다.
SHL : Destination 피연산자를 Source피연산자의 크기만큼 왼쪽으로 쉬프트연산한다.
쉬프트된 최상위 비트는 CF로 복사되고 최하위비트는 0으로 채워진다
ex) SHL Destination, Source
Destination = 10010000
Source = 1
>> Destination = 00100000, CF = 1
SHR : Destination 피연산자를 Source피연산자의 크기만큼 오른쪽으로 쉬프트연산한다.
쉬프트된 최하위 비트는 CF로 복사되고 최상위비트는 0으로 채워진다
ex) SHL Destination, Source
Destination = 10010001
Source = 1
>> Destination = 01001000, CF = 1
PUSH :스택에 값을 넣는다
ESP의 값이 4만큼 줄어들고 이 위치에 새로운 값이 채워진다.
PUSHAD : EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP 레지스터의 값을 스택에 PUSH한다.
레지스터의 값들을 보관할 때 사용한다.
PUSHFD : 플래그 레지스터를 스택에 PUSH한다.
플래그 레지스터값을 보관할 때 사용한다.
POP : ESP 레지스터가 가리키고 있는 위치의 스택 공간에서 4byte만큼을 Destination 피연산자에 복사하고 ESP레지스터의 값에 4를 더한다.
POPAD : 스택에 존재하는 값을 EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP레지스터로 POP한다.
PUSHAD 로 스택에 보관해 놓은 레지스터 정보를 다시 이용하려고 할 때 사용한다.
POPFD : 스택에 존재하는 값을 플래그 레지스터로 POP한다.
PUSHFD 로 스택에 보관해 놓은 플래그 레지스터 정보를 다시 이용하려고 할 때 사용한다.
XCHG : 두 피연산자의 내용이 서로 교환된다.
IMM값은 피연산자가 될 수 없다.
NEG : 피연산자의 2의 보수를 계산하여 결과를 피연산자에 저장한다.
PTR : 피연산자의 크기를 재설정한다.
ex) MOV eax DWORD PRT value
value의 크기를 DWORD크기로 재설정하여 eax 레지스터에 복사하라는 뜻이다.
OFFSET : 세그먼트의 시작으로부터 변수가 위치한 거리까지의 상대적 거리를 리터한다.
ex) MOV esi, OFFSET value
value가 존재하는 위치를 세그먼트 시작 지점부터의 상대적 거리를 구해서 esi 레지스터에 복사하라는 의미이다.
LEA : Source 피연산자의 유효 주소를 계산하여 Destination 피연산자에 복사한다.
ex) LEA Destination, Source
Destination에는 레지스터만 올 수 있다.
LEA EAX, [EBP + 10]
EBP주소의 값에 10을 더한뒤 EAX에 대입한다. >> MOV에서의 주소연산과 다름
REP : ECX 레지스터를 카운터로 사용해서 문자열 관련 명령을 ECX > 0동안 반복한다.
JMP : 피연산자의 위치로 실행 흐름이 변경된다.
short jmp는 -127~127바이트 범위 안에서 사용된다.
near jmp는 세그먼트 내부에서 사용된다.
far jmp는 현재 세그먼트를 벗어날 때 사용한다.
jmp명령어는 돌아올 리턴 어드레스를 저장하지 않는다.
CALL : jmp명령어와 같이 실행흐름이 변경되지만 CALL명령어는 리턴 어드레스를 스택에 저장한다.
CMP : 두 피연산자를 비교하는 작업을 한다.
두 피연산자의 값이 같다면 결과는 0이되고 ZF 가 1로 세트된다.
다르다면 0으로 세트된다.
NOP : 아무일도 하지 않는 명령어이다.
이미 있는 명령어를 삭제할 때 사용.
비교구문 cmp와 test
cmp명령어는 주어지는 두 값을 뺄셈을 해서 처리하고, test명령어는 주어지는 두 값을 더해서 처리한다.
cmp eax, ebx 이면 두 값을 빼서 0이면 참이되는 형태이다.
test eax, ebx 이면 두 값을하는대 이때 발생하는 플래그들만 저장을 한다.
CMP는 ZF, OF, SF, CF에 영향을 미친다.
TEST는 SF, ZF, PF에 영향을 미친다.
ZF = 1로 세팅되어 있다면 두 값이 같다는 의미이다.
OF, SF, CF를 이용해서 어느쪽이 더 큰지를 알 수 있다.
조건 점프 명령
명령어 |
명령어의 의미 |
명령어가 수행되기 위한 플래그 레지스터와 볌용 레지스터의 상태 |
JA |
Jump if (unsigned) above |
CF = 0 and ZF = 0 |
JAE |
Jump if (unsigned) above or equal |
CF = 0 |
JB |
Jump if (unsigned) below |
CF = 1 |
JBE |
Jump if (unsigned) below or equal |
CF = 1 or ZF = 1 |
JC |
Jump if carry flag set |
CF = 1 |
JCXZ |
Jump if CX is 0 |
CX = 0 |
JE |
Jump if equal |
ZF = 1 |
JECX |
Jump if ECX is 0 |
ECX = 0 |
JG |
Jump if (signed) greater |
ZF = 0 and SF = 0 |
JGE |
Jump if (signed) greater or equal |
SF = OF |
JL |
Jump if (signed) less |
SF != OF |
JLE |
Jump if (signed) less or equal |
ZF = 1 and OF != OF |
JNA |
Jump if (unsigned) not above |
CF = 1 or ZF = 1 |
JNAE |
Jump if (unsigned) not above or equal |
CF = 1 |
JNB |
Jump if (unsigned) below |
CF = 0 |
JNBE |
Jump if (unsigned) below or equal |
CF = 0 and ZF = 0 |
JNC |
Jump if carry flag not set |
CF = 0 |
JNE |
Jump if not equal |
ZF = 0 |
JNG |
Jump if (signed) not greater |
ZF = 1 or SF != OF |
JNGE |
Jump if (signed) not greater or equal |
SF != OF |
JNL |
Jump if (signed) not less |
SF = OF |
JNLE |
Jump if (signed) not less or equal |
ZF = 0 and SF = OF |
JNO |
Jump if overflow flag not set |
OF = 0 |
JNP |
Jump if parity flag not set |
PF = 0 |
JNS |
Jump if sign flag not set |
SF = 0 |
JNZ |
Jump if not zero |
ZF = 0 |
JO |
Jump if overflow flag is set |
OF = 1 |
JP |
Jump if parity flag is set |
PF = 1 |
JPE |
Jump if parity is equal |
PF = 1 |
JPO |
Jump if parity is odd |
PF = 0 |
JS |
Jump if sign flag is set |
SF = 1 |
JZ |
Jump if zero |
ZF = 1 |
전역변수
전역변수의 경우 DATA 섹션에 저장되고, 프로그램을 초기화 하는 과정에서 세팅되거나 실행중에 변경이 될 수도 있다.
ex)
.data : 0088A1A1 'This Program is powerful', 0
data섹션에 문자열이 들어 있다면
.text : 006A2A22 mov eax, 88A1A1h
.text : 006A2A27 retn
분기문의 사용
C언어 에서 if문은 어셈블리어에서 조건 점프문으로 대체할 수 있다.
반복문의 사용
반복문의 경우에는 같은 내용이 반복처리되다가 반복문을 종료하는 비교문을 만나서 점프하여 반복문을 벗어나도록 구현되어있다.
cmp, jnz이용하여 ecx에 들어있는 값만큼 반복할 수 있다.
함수의 사용
함수의 시작부분과 끝나는 부분을 확인할 수 있는 구분자가 있어서 확인이 그리 어렵지 않다.
시작부분에서는 push명령어를 통해 현재 레지스터값들을 스택에 넣어두고 함수를 진행하고
끝나는 부분은 호출이 끝나서 리턴되기 ret명령어가 쓰여있다.
'Study > Reversing' 카테고리의 다른 글
키젠문제 풀이 (0) | 2015.05.18 |
---|---|
Unpack, Back To User mode (0) | 2015.05.18 |
CPU레지스터와 데이터타입 (0) | 2015.05.15 |
abexcm1.exe풀이 (0) | 2015.05.14 |
올리디버거 다운로드 및 설정 (1) | 2015.05.13 |
댓글