[3] 어셈블리 text section / mov / lea

2017. 10. 17. 19:58SystemHacking/Assembly





[ 명령어 ]

1. MOV

할당 연산자와 비슷한 개념

mov r/m reg

mov reg r/m

mov r/m 상수


기본적인 형태 : mov dst, src ( src,dst 에 memory가 올 수 는 없다 )


1-1> 레지스터에 데이터 저장하기

mov eax, 10        ; eax레지스터에 상수 10을 저장


1-2> 메모리에 데이터 저장하기

mov 크기 [레이블], 값    ; 레이블에 해당하는 주소안에 '크기' 만큼의 공간에 값을 저장


 

[ #vi operator.asm ]

     


[ 코드 설명 ]

 

 extern printf

 section .data

 argv1:    db    '%d', 10, 00

 test_1:    dd    10

 section .bss

 memory1:    resd    1

 section .text

 global main

 main:


        mov     eax,    10      ; int eax=10

        push    eax

        push    argv1

        call    printf                                        ; register에 값을 저장하는 방식

                                                                ; printf("%d",10)


        mov     dword [memory1],        10        ; 형식 : 명령어 크기 [ 메모리주소 ], 상수

        push    dword [memory1]                     ; => 해당 주소(memory1)에 위치하는 4byte크기의 값을 가져옴

        push    argv1

        call    printf                                         ; memory에 값을 저장하는 방식

                                                                 ; printf("%d",10)


    => memory1은 레이블이다. CPU가 사용하는 메모리의 주소를 가리킨다 ( 0x08080808 같은 형식 )

         오류발생시: operator.asm:19: error: invalid combination of opcode and operands

    => 메모리는 크기를 지정해주어서 NASM이 읽어갈 수 있도록 해야한다 

         오류발생시: operator.asm:20: error: operation size not specified


        mov     ebx,    dword [test_1]            ; ebx 레지스터를 메모리의 test_1주소 부터 4byte만큼크기의 데이터로 초기화

        push    ebx                                     ; ebx 레지스터에 있는 값을 printf함수의 인자로 넣는다

        push    argv1                                  ; argv1레이블에 있는 값을 printf함수의 인자로 넣는다

        call    printf                                    ; printf( argv1 , ebx ) = printf("%d",100)

 

 

 

[ #vi operator.asm ]

 

[ 코드 설명 ]

 

 extern printf

 section .data

 argv1:    db    '%d', 10, 00  

 argv2:    db    '%c', 10, 00

 string:    db    'korea',10,00

 buffer:    dd    10,20,30,40,50 ; 4byte크기만큼 buffer:시작주소부터 차례대로 주소에 값이 들어간다

 

 section .text

 global main

 main:


        mov al, byte [string]                    ; al 레지스터에 byte크기의 해당주소(string)에 있는 값을 입력

        push eax

        push argv2

        call printf                                   ; printf('%c",'k') : k

 

        mov bl, byte [string+1]                 ; bl 레지스터에 byte크기의 해당주소(string+1)에 있는 값을 입력

        push bx

        push argv2

        call printf                                    ; printf("%c",'o') : o


        mov ecx dword [buffer+2*4]

        push ecx

        push argv1

        call printf                                     ; printf("%d",buffer[1]) : 30
 

 


* C언어 에서의 배열과 비슷하게 배열안의 인자 값의 크기에 따라서 주소값을 더해주고 빼주면 된다

* 어셈블리에서는 +,-,* 연산자를 사용할 수 없어서 명령어로 사용하지만, " [ ] " 내부에서는 사용할 수 있다 


* 해당 코드에서 사용한 string 과 buffer 레이블의 주소에서의 모습은 다음과 같다


[ string 레이블 ]

 주소

string

string+1 

 string+2

string+3 

string+4 

 값 

 k

r


[ buffer 레이블 ]

주소 

buffer 

buffer+4 

buffer+8 

buffer+12 

buffer+16 

10 

20 

30 

40 

50 


[ 실행 결과 ]


 

 

2> LEA ( Load Effective Address ) : 단순히 주소값을 다룬다고 생각하면 된다 ( mov는 주소안의 값을 다룬다 )


[ #vi operator.asm ]

 

[ 코드 설명 ]

 

 extern printf

 section .text

 global main

 main:

    lea     eax,    [10+10]              ; eax레지스터를 주소값 20으로 초기화

    push    dword [eax]                ; eax레지스터에는 단순히 20 이 저장되어 있고 [] 처리하여 20이라는 주소의 값을 가져옴

    push    argv1                         ; => 주소값 20에 접근할 수 없기때문에 오류가 발생한다

    call    printf                          

 

    mov     ecx,    buffer               ; buffer를 ecx레지스터에 저장 ( buffer는 메모리의 주소값 )

    lea     ebx,    [ecx+16]             ; ecx에저장된 주소(=buffer)에서 16byte 이동한 주소를 ebx레지스터에 저장

    mov     dword [ebx],    100      ; ebx레지스터에 저장된 값(주소값)을 [] 처리하여, 해당 주소의 값을 100으로 초기화

    push    dword [ebx]                ; ebx레지스터에 저장된 값을 []처리하여 해당 주소의 값을 가져오고

                                               ; printf함수의 인자로 입력

    push    argv1    

    call    printf                           ; printf("%d",buffer[4])


 

 

[ 실행 결과 ]

 

 

* 요약


1. 레이블은 변수가 아니다

data section에서 선언한 것을 예로 들어서 봐보자


section .data

exam:    dd    1,2,3,4,5

=> exam은 { 1,2,3,4,5 } 의 시작주소라고 보면된다

=> C언어로 설명하자면 exam[0]=1 , exam[1]=2 ... 와 같다

2. 해당 메모리 주소를 text섹션에서 사용하는 방법


section .text

global main

main:    

mov al, dword [exam]

mov bl, dword [exam+1*4]


( * 항상 기억해야할 것 exam 은 data section에서 선언한 레이블이다. 변수가 아니다. 즉 주소값이다. ex) 0x80801212 ) )

 

# al 레지스터에 4byte(dd) 크기의 exam주소에 들어있는 값을 저장하겠다    

=> al 레지스터에 1을 넣는다  ( C언어로 설명하자면 exam의 첫번째 인자 )


# bl 레지스터에 4byte(dd) 크기의 exam+4 주소에 들어있는 값을 저장하겠다    

=> bl 레지스터에 2를 넣는다  ( C언어로 설명하자면 exam의 두번째 인자 )