2017. 10. 17. 19:58ㆍSystemHacking/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 |
o |
r |
e |
a |
[ 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의 두번째 인자 )
'SystemHacking > Assembly' 카테고리의 다른 글
[6] 어셈블리 비트연산 ( shift, and, or, not ) (0) | 2017.10.20 |
---|---|
[5] 어셈블리 계산기 , scanf , printf (0) | 2017.10.19 |
[4] 어셈블리 명령어 add,sub,mul,div (0) | 2017.10.18 |
[2] 어셈블리 문자열 표현방식 / 데이터단위 / 레지스터 종류 (0) | 2017.10.16 |
[1] 어셈블리 배경지식 / xxd, objdump 명령어 사용법 (0) | 2017.10.15 |