데이터 이동
mov
src에 들어있는 값을 dst에 대입합니다.
mov rdi, rsi; //rdi에 rsi값을 대입
lea
src의 주소를 dst 저장합니다.
lea rsi, [rbx+8*rcx]; //rbx+8*rcx를 rsi에 대입
산술 연산
add
dst에 src의 값을 더합니다
add eax, 3; // eax += 3
sub
dst에서 src의 값을 뺍니다
sub eax, 3; // eax -= 3
inc
op의 값을 1 증가시킵니다.
inc eax; // eax += 1
dec
op의 값을 1 감소시킵니다.
dec eax; // eax -= 1
논리연산
and
dst와 src의 and연산
[Register] eax = 0xffff0000; ebx = 0xabcdefff; [Code] and eax, ebx; [Result] eax = 0xabcd0000;
or
dst와 src의 or연산
[Register] eax = 0xffff0000; ebx = 0xabcdefff; [Code] or eax, ebx; [Result] eax = 0xffffefff;
xor
dst와 src의 xor연산
[Register] eax = 0xffff0000; ebx = 0xabcdefff; [Code] xor eax, ebx; [Result] eax = 0x5432efff;
not
op의 비트 전부 반전
[Register] eax = 0xffff0000; [Code] not eax; [Result] eax = 0x0000ffff;
비교
cmp
두 피연산자를 빼서 대소를 비교합니다. 결과 값을 op1에 대입하지 않습니다.
만약 두 수의 뺄셈 결과 값이 0이면 ZF 플래그를 설정합니다.
[Code] mov rax, 0xA; mov rbx, 0xA; cmp rax, rbx; // ZF = 1
test
두 피연산를 and연산 합니다. 결과 값을 op1에 대입하지 않습니다.
test를 통해 ZF플래그 값이 설정되면, rax의 값이 0 이라는 것을 판단 할 수 있습니다.
[Code] xor rax, rax; test rax, rax; // ZF = 1
분기
jmp
addr로 rip를 이동시킵니다.
[Code] 1: xor rax, rax; 2: jmp 1; jump to 1
je
직전에 비교한 두 피연산자가 같으면 이동시킵니다.
[Code] 1: mov rax, 0xffffffff 2: mov rbx, 0xffffffff 3: cmp rax, rbx ; rax == rbx 4: je 1 ; jump to 1
jg
직전에 비교한 두 연산자 중 전자가 더 크면 점프
[Code] 1: mov rax, 0x31337 2: mov rbx, 0x13337 3: cmp rax, rbx ; rax > rbx 4: jg 1 ; jump to 1
스택
push
value를 스택 최상단에 쌓음
[Register] rsp = 0x7fffffffc400 [Stack] 0x7fffffffc400 | 0x0 <- rsp 0x7fffffffc408 | 0x0 [Code] push 0x31337 [Result] [Register] rsp = 0x7fffffffc3f8 [Stack] 0x7fffffffc3f8 | 0x31337 <- rsp 0x7fffffffc400 | 0x0 0x7fffffffc408 | 0x0
pop
스택의 최상단 값을 꺼내서 reg에 대입
[Register] rax = 0 rsp = 0x7fffffffc3f8 [Stack] 0x7fffffffc3f8 | 0x31337 <- rsp 0x7fffffffc400 | 0x0 0x7fffffffc408 | 0x0 [Code] pop rax [Result] [Register] rax = 0x31337 rsp = 0x7fffffffc400 [Stack] 0x7fffffffc400 | 0x0 <- rsp 0x7fffffffc408 | 0x0
프로시저
프로시저는 특정 기능을 수행하는 코드 조각을 말한다.
call
addr에 위치한 프로시저 호출
프로시저를 실행하고 나서는 원래 실행 흐름으로 들어와야 하므로 스택에 call 다음 명령어 주소를 저장하고 프로시저로 rip를 이동시킨다.
[Register] rip = 0x400000 rsp = 0x7fffffffc400 [Stack] 0x7fffffffc3f8 | 0x0 0x7fffffffc400 | 0x0 <- rsp [Code] 0x400000 | call 0x401000 <- rip 0x400005 | mov esi, eax ... 0x401000 | push rbp [Result] [Register] rip = 0x401000 rsp = 0x7fffffffc3f8 [Stack] 0x7fffffffc3f8 | 0x400005 <- rsp 0x7fffffffc400 | 0x0 [Code] 0x400000 | call 0x401000 0x400005 | mov esi, eax ... 0x401000 | push rbp <- rip
ret
스택에 저장되어있는 Return Address를 꺼내어 rip에 대입합니다.
[Register] rip = 0x401008 rsp = 0x7fffffffc3f8 [Stack] 0x7fffffffc3f8 | 0x400005 <- rsp 0x7fffffffc400 | 0 [Code] 0x400000 | call 0x401000 0x400005 | mov esi, eax ... 0x401000 | mov rbp, rsp ... 0x401007 | leave 0x401008 | ret <- rip [Result] [Register] rip = 0x400005 rsp = 0x7fffffffc400 [Stack] 0x7fffffffc3f8 | 0x400005 0x7fffffffc400 | 0x0 <- rsp [Code] 0x400000 | call 0x401000 0x400005 | mov esi, eax <- rip ... 0x401000 | mov rbp, rsp ... 0x401007 | leave 0x401008 | ret