어셈블리어 | Assembly Language
컴퓨터의 기계어와 치환되는 언어
명령어(Opcode)와 피연산자(Operand)로 구성된다.
명령어(Opcode)
x64의 중요한 21개의 명령어
명령 코드 | |
데이터 이동(Data Transfer) | mov, lea |
산술 연산(Arithmetic) | inc, dec, add, sub |
논리 연산(Logical) | and, or, xor, not |
비교(Conmparison) | cmp, test |
분기(Branch) | jmp, je, jg |
스택(Stack) | push, pop |
프로시져(Procedure) | call, ret, leave |
시스템 콜(System call) | syscall |
피연산자(Operand)
피연산자에는 총 3가지 종유가 올 수 있다.
상수(Immediate Value)
레지스터(Register)
메모리(Memory)
메모리 피연산자는 []으로 둘러싸인 것으로 표현되며, 앞에 크기 지정자(Size Directive) TYPE PTR이 추가될 수 있습니다.
타입에는 BYTE, WORD, DWORD, QWORD가 올 수 있다.
각각 1바이트, 2바이트, 4바이트, 8바이트의 크기를 지정한다.
메모리 피연산자 | |
QWORD PTR [0x8048000] |
0x8048000의 데이터를 8바이트만큼 참조 |
DWORD PTR [0x8048000] |
0x8048000의 데이터를 4바이트만큼 참조 |
WORD PTR [rax] |
rax가 가르키는 주소에서 데이터를 2바이트 만큼 참조 |
어셈블리_명령어
데이터 이동
테이터 이동 명령어는 어떤 값을 레지스터나 메모리에 옮기도록 지시합니다.
mov dst, src : src에 들어있는 값을 dst에 대입 | |
mov rdi, rsi | rsi의 값을 rdi에 대입 |
mov QWORD PTR[rdi], rsi | rsi의 값을 rdi가 가리키는 주소에 대입 |
mov QWORD PTR[rdi+8*rcx], rsi | rsi의 값을 rdi+8*rcx가 가리키는 주소에 대입 |
lea dst, src : src의 유효 주소(Effective Address, EA)를 dst에 저장합니다. | |
lea rsi, [rbx+8*rcx] | rbx+8*rcx 를 rsi에 대입 |
*mov는 주소의 값을 대입, lea는 주소를 저장 하는 것
산술 연산
add dst, src : dst에 src의 값을 더합니다. | |
add eax, 3 | eax += 3 |
add ax, WORD PTR[rdi] | ax += *(WORD *)rdi |
sub dst, src: dst에서 src의 값을 뺍니다. | |
sub eax, 3 | eax -= 3 |
sub ax, WORD PTR[rdi] | ax -= *(WORD *)rdi |
inc op: op의 값을 1 증가 시킴 | |
inc eax | eax += 1 |
dec op: op의 값을 1 감소 시킴 | |
dec eax | eax -= 1 |
논리 연산
and dst, src: dst와 src의 비트가 모두 1이면 1, 아니면 0
[Register]
eax = 0xffff0000
ebx = 0xcafebabe
[Code]
and eax, ebx
[Result]
eax = 0xcafe0000
or dst, src: dst와 src의 비트 중 하나라도 1이면 1, 아니면 0
[Register]
eax = 0xffff0000
ebx = 0xcafebabe
[Code]
or eax, ebx
[Result]
eax = 0xffffbabe
xor dst, src: dst와 src의 비트가 서로 다르면 1, 같으면 0
[Register]
eax = 0xffffffff
ebx = 0xcafebabe
[Code]
xor eax, ebx
[Result]
eax = 0x35014541
*xor연산을 동일한 값으로 두 번 실행할 경우, 원래 값으로 돌아갑니다.
not op: op의 비트 전부 반전
[Register]
eax = 0xffffffff
[Code]
not eax
[Result]
eax = 0x00000000
비교
두 피연산자 값을 비교하고, 플래그를 설정한다.
cmp op1, op2: op1과 op2를 비교
[Code]
1: mov rax, 0xA
2: mov rbx, 0xA
3: cmp rax, rbx ; ZF=1
test op1, op2: op1과 op2를 비교
[Code]
1: xor rax, rax
2: test rax, rax ; ZF=1
분기
분기 명령어는 rip를 이동시켜 실행 흐름을 바꾼다.
jmp addr: addr로 rip를 이동시킵니다.jmp addr: addr로 rip를 이동시킵니다.
[Code]
1: xor rax, rax
2: jmp 1 ; jump to 1
je addr: 직전에 비교한 두 피연산자가 같으면 점프 (jump if equal)
[Code]
1: mov rax, 0xcafebabe
2: mov rbx, 0xcafebabe
3: cmp rax, rbx ; rax == rbx
4: je 1 ; jump to 1
jg addr: 직전에 비교한 두 연산자 중 전자가 더 크면 점프 (jump if greater)
[Code]
1: mov rax, 0x31337
2: mov rbx, 0x13337
3: cmp rax, rbx ; rax > rbx
4: jg 1 ; jump to 1