반응형
데이터 전송 명령어
데이터 전송 명령어
MOV 명령어 (move) | ||
MOV [피연산자1] [피연산자2] | ||
[피연산자1]에 [피연산자2]의 값을 대입한다. | ||
MOV EAX, 1 | ||
EAX에 1을 대입하여 저장한다 [피연산자1]은 데이터 목적지이며, [피연산자2]는 이동의 대상이다. [피연산자1]은 레지스터, 메모리가 될 수 있고, [피연산자2]는 값, 레지스터, 메모리가 될 수 있다. |
PUSH 명령어 (push) | ||
PUSH [피연산자1] | ||
[피연산자1]을 스택에 저장한다. | ||
PUSH EAX | ||
EAX를 스택에 저장한다. 스택포인터는 [피연산자1] 크기만큼 감소한다. |
POP 명령어 (pop) | ||
POP [피연산자1] | ||
[피연산자1]에 스택의 최상단 꺼내어 값을 저장한다. | ||
POP EAX | ||
EAX에 스택의 최상단 값을 꺼내 저장한다. 스택 포인터는 [피연산자1]에 대입한 크기만큼 증가한다. |
LEA 명령어 (load effective address to register) | ||
LEA [피연산자1] [피연산자2] | ||
[피연산자1]에 [피연산자2]의 메모리의 값을 가져오는 것이 아닌 메모리 주소를 계산해서 그 주소 자체를 레지스터에 저장한다. | ||
LEA EAX, BP+1 | ||
EAX에 BP의 주소값에 +1을 하는 것이 아닌 BP의 주고값의 결과값에 +1을 한다. BP의 주소가 0x0004이고 값이 3이라면 MOV 명령어에서는 0x0005 주소 값을 가져오고 LEA에서는 0x0004의 값인 3 + 1을 하여 4를 대입한다 mov ebx, 100 mov ecx, 5 ; EAX = EBX + ECX*4 (100 + 5*4 = 120)을 계산하고 싶을 때 ; 일반적인 방법 ; mov eax, ecx ; mul eax, 4 ; MUL은 다른 레지스터(EDX)에도 영향을 줘서 복잡 ; add eax, ebx ; LEA를 사용한 방법: lea eax, [ebx + ecx*4] ; 단 한 줄로 플래그 변화 없이 eax = 120 이라는 계산이 완료된다. 매우 효율적 |
XCHG 명령어 (exchange register / memory with register) | ||
XCHG [피연산자1] [피연산자2] | ||
[피연산자1]와 [피연산자2]의 값을 맞바꾼다. | ||
XCHG EAX, EBX | ||
EAX와 EBX의 값을 바꾼다(swap). mov eax, 10 mov ebx, 20 ; EAX와 EBX의 값을 서로 바꾼다 xchg eax, ebx ; 결과: EAX = 20, EBX = 10 |
IN 명령어 (input form AL / AX to fixed port) | ||
IN [피연산자1] [피연산자2] | ||
[피연산자1]은 AL/AX/EAX이 가능하며 [피연산자2]로 지시한 포트로 AX에 데이터를 입력한다. 하드웨어 장치(Device)와 통신하기 위해 사용되는 특수한 명령어이다. 커널 모드(운영체제)에서만 사용 가능한 특권 명령어이다. |
||
IN AL, 0x64 | ||
; 키보드 컨트롤러의 상태 포트(0x64)에서 상태 값을 읽는다고 가정 in al, 0x64 ; 포트 0x64에서 1바이트를 읽어 AL에 저장 ; 포트 주소가 255를 넘을 경우 DX 레지스터 사용 mov dx, 0x3F8 ; 직렬 포트(COM1)의 주소 in al, dx ; COM1 포트에서 데이터를 읽어옴 |
OUT 명령어 (Output form AL / AX to fixed port) | ||
OUT [피연산자1] [피연산자2] | ||
[피연산자1]은 AL/AX/EAX이 가능하며 [피연산자2]로 지시한 포트로 AX에 데이터를 입력한다. 하드웨어 장치(Device)와 통신하기 위해 사용되는 특수한 명령어이다. 커널 모드(운영체제)에서만 사용 가능한 특권 명령어이다. |
||
OUT 0x61, AL | ||
; PC 스피커를 제어하는 포트(0x61)에 값을 쓴다고 가정 out 0x61, al ; AL의 값(0xFF)을 포트 0x61로 내보냄 |
XLAT 명령어 (translate byte to AL) | ||
XLAT | ||
BX:AL 지시한 테이블 내용을 AL로 로드한다. 주로 데이터 테이블에서 값을 변환하거나, 코드 페이지를 변환하는 등 다양한 데이터 조작 작업에 사용한다. |
||
XLAT | ||
section .data hex_to_ascii_table db '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' section .text ; 7을 '7'로 변환하고 싶다고 가정 lea ebx, [hex_to_ascii_table] ; EBX에 테이블의 시작 주소를 저장 mov al, 7 ; AL에 찾고 싶은 값(인덱스) 7을 저장 xlat ; XLAT 명령어 실행 ; 동작 EBX 주소에서 7바이트 떨어진 위치('7')의 값을 읽어 AL에 덮어쓴다. ; 결과 AL = '7' (ASCII 값 0x37) |
LES 명령어 (load pointer to ES) | ||
LES [피연산자1] [피연산자2] | ||
[피연산자1]에 [피연산자2]의 메모리의 값을 가져오는 것이 아닌 메모리 주소를 계산해서 그 주소 자체를 다른 ES 데이터의 주소 내용을 참조할때 사용한다. [피연산자2] 위치에서 2개의 워드를 읽어와 ES:SI 레지스터에 로드 |
||
LES BX, 0x0004 | ||
section .data ; Far Pointer 정의: dw는 2바이트(Word) far_pointer dw 0x1234, 0xABCD ; 앞이 오프셋(1234h), 뒤가 세그먼트(ABCDh) section .text ; ... les bx, [far_pointer] ; 결과: ; BX = 0x1234 (오프셋) ; ES = 0xABCD (세그먼트) ; 이제 ES:BX를 통해 0xABCD:0x1234 주소의 데이터에 접근 가능하다 |
LAHF 명령어 (load AH with flags) | ||
LAHF | ||
플래그 내용을 AH의 특정 비트로 로드한다. | ||
LAHF | ||
sub eax, eax ; EAX를 0으로 만듦. 이 연산으로 Zero Flag(ZF)가 1이 된다. lahf ; EFLAGS의 하위 바이트를 AH에 복사 ; 이제 AH의 6번 비트(Zero Flag 위치)가 1이 되었는지 테스트할 수 있다. ; AH의 값은 01000110b (0x46) 근처가 된다. (ZF=1, PF=1) test ah, 0x40 ; AH의 6번 비트(0100 0000b)가 세팅되었는지 확인 jnz is_zero ; 0이 아니면(ZF가 1이었으면) is_zero 함수로 점프 |
SAHF 명령어 (store AH with flags) | ||
SAHF | ||
AH의 특정 비트를 플래그 레지스터로 전송한다. | ||
SAHF | ||
; 캐리 플래그(CF)는 EFLAGS의 최하위 비트(0번 비트)이다. ; LAHF로 현재 플래그를 읽고 CF 비트만 1로 만든 후 SAHF로 다시 쓴다. lahf ; 현재 플래그 상태를 AH에 로드 or ah, 0x01 ; AH의 0번 비트를 1로 OR 연산 (다른 플래그는 유지) sahf ; 조작된 AH 값을 플래그 레지스터에 다시 쓴다. ; 이제 캐리 플래그(CF)는 1이 된다 jc carry_is_set ; 캐리가 세팅되었으므로 이 점프는 반드시 실행된다. |
PUSHF 계열 명령어 (push flags) | ||
PUSHF / PUSHFD / PUSHFQ | ||
플래그 레지스터 내용을 스택에 삽입한다. PUSHF: 16비트 FLAGS 레지스터를 PUSH 한다. PUSHFD: 32비트 EFLAGS 레지스터를 PUSH 한다. PUSHFQ: 64비트 RFLAGS 레지스터를 PUSH 한다. |
||
PUSHF / PUSHFD / PUSHFQ | ||
cmp eax, ebx ; eax와 ebx를 비교. 결과에 따라 플래그들이 변경됨. pushfd ; 현재 EFLAGS의 모든 상태를 스택에 백업한다 ; ... 다른 작업 수행 (이 과정에서 플래그가 마구 변경됨) call SomeFunction ; 이제 원래 플래그 상태가 필요하다. popfd ; 스택에서 백업해 둔 값을 꺼내 EFLAGS를 완벽히 복원 je values_were_equal ; 복원된 플래그를 기반으로 점프. (cmp 결과가 같았다면 점프 성공) |
POPF 계열 명령어 (push flags) | ||
POPF / POPFD / POPFQ | ||
스택에서 값을 꺼내 플래그 레지스터에 덮어씀으로써 CPU의 플래그 상태를 복원한다. 스택에 저장된 플래그 레지스터 값을 삭제한다. POPF: 16비트 FLAGS 레지스터로 POP 한다. POPFD: 32비트 EFLAGS 레지스터로 POP 한다. POPFQ: 64비트 RFLAGS 레지스터로 POP 한다. |
||
POPF / POPFD / POPFQ | ||
pushfd ; 1. 현재 플래그를 스택에 저장한다 pop eax ; 2. 스택에 저장된 플래그 값을 EAX로 가져온다 or eax, 0x0100 ; 3. EAX에서 방향 플래그(Direction Flag, DF) 비트(10번 비트)를 1로 세팅 push eax ; 4. 조작된 EAX 값을 다시 스택에 넣는다 popfd ; 5. 스택의 값을 EFLAGS로 복원한다. DF=1이 된다. ; 이제 문자열 명령(예: movsb)은 주소를 감소하는 방향으로 동작한다. |
반응형
'시스템 > 리버싱' 카테고리의 다른 글
어셈블리 논리 명령어 (0) | 2025.06.24 |
---|---|
어셈블리 산술 연산 명령어 (0) | 2025.06.22 |
레지스터 (0) | 2025.06.09 |
dreamhack Quiz:x86 Assembly 2 (0) | 2022.08.25 |