본문 바로가기

어셈블리 전송 명령어

@enable79972025. 6. 23. 15:19
반응형

데이터 전송 명령어

데이터 전송 명령어

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
목차