Assembly

x86 assembly data move instruction

jdaemanv2 2022. 1. 9. 14:41

[1. 데이터 이동]

 

mov <reg> <reg>

=> 두번째 피연산자에 명시 된 레지스터에 저장된 값을 첫번째 피연산자에 명시 된 레지스터에 저장한다.

 

mov <reg> <mem>

=> 두번째 피연산자에 명시 된 메모리 주소에 저장 된 값을 첫번째 피연산자에 명시 된 레지스터에 저장한다.

 

mov <mem> <reg>

=> 두번째 피연산자에 명시 된 레지스터에 저장 된 값을 첫번째 피연산자에 명시 된 메모리 주소에 저장한다.

 

mov <reg> <const>

mov <mem> <const>

=> 두번째 피연산자에 명시 된 상수 값을 첫번째 피연산자에 명시 된 레지스터/메모리 주소에 저장한다.

; example code

section .bss
        num resb 8        ; reserve 8bytes
        num1 resb 8

section .text
        global _start

_start:
        mov rax, 0x50
        mov ebx, 0x30

        mov r10, num        ; store num address
        mov r11, num1
        mov DWORD [num], 0x12345678
        mov DWORD [num+4], 0x12345678
        mov cl, BYTE [num]   ; 0x78
        mov dx, WORD [num]   ; 0x5678
        mov r8d, DWORD [num] ; 0x12345678
        mov r9, QWORD [num]

        mov r12, 0x9876543210987654
        mov QWORD [num1], r12

        mov rax, 60
        mov rdi, 0
        syscall

num 은 8byte 공간이 할당되었지만,

mov 명령어에서 두번째 피연산자로 상수 값이 오는 경우 4byte 까지만 할당이 가능하다.

따라서 8byte 공간을 초기화 하기 위해 4바이트를 두번에 걸쳐서 초기화 시킨다.

 

그리고 indirection addressing mode 를 사용할 때에는 BYTE, WORD, DWORD, QWORD 와 같은 키워드를 이용하여

얼마만큼 이동 시킬 지 그 byte 값을 명시해야 한다.

아래는 위 코드 실행 시 각 레지스터 및 메모리에 저장된 값을 보여 준다.

 

 

[2. Stack 관련 명령어]

메모리내 하드웨어 지원 스택을 사용 할 수 있게 해주는 명령어로

RSP 레지스터를 이용해서 직접 메모리 주소를 직접 계산하면서 stack 을 활용 할 수 도 있다.

 

push <reg>       <->   pop <reg>

push <mem>     <->   pop <mem>

push <const>     <->   pop <const>

 

; example code

section .text
        global _start

_start:
        mov rax, 0x1111111111111111
        push rax
        inc rax ; rax=rax+1
        push rax
        inc rax

        pop rbx ; expect 0x1111111111111111
        pop rcx ; expect 0x1111111111111112

        mov rbp, rsp ; rbp point to top of stack
        mov DWORD [rbp-4], 0x12345678 ; like push
        mov DWORD [rbp-8], 0x87654321

        mov edx, DWORD [rbp-8]        ; like pop
        mov r8d, DWORD [rbp-4]

        mov rax, 60
        mov rdi, 0
        syscall

위 코드는 push/pop instruction 을 통해 stack 을 사용하는 것과

stack pointer 를 직접 제어하여 stack 을 사용하는 두가지 방식을 보여주고 있다.

 

stack pointer 를 직접 제어하는 방식에서

DWORD 의 크기는 4bytes 이므로, 현재 stack 은 아래와 같은 상태가 된다.

stack: 

       [<---0x12345678--->]

       [<---0x87654321--->]

 

 

아래는 실제로 각 레지스터에 할당된 값을 보여주고 있다.

 

 

[3. 메모리 주소 관련 명령어]

LEA = Load Effective Address

 

 

 

 

 

[4. 참고자료]

https://www.cs.virginia.edu/~evans/cs216/guides/x86.html

https://stackoverflow.com/questions/46395630/moving-64-bit-constant-to-memory-in-x86-assembly/46395752

https://c9x.me/x86/html/file_module_x86_id_153.html