데이터 이동
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에 대입 |
퀴즈!
[Register]
rbx = 0x401A40
=================================
[Memory]
0x401a40 | 0x0000000012345678
0x401a48 | 0x0000000000C0FFEE
0x401a50 | 0x00000000DEADBEEF
0x401a58 | 0x00000000CAFEBABE
0x401a60 | 0x0000000087654321
=================================
[Code]
1: mov rax, [rbx+8]
2: lea rax, [rbx+8]
- Code 1까지 실행 후 rax에 저장되는 값은?
0xC0FFEE - Code 2까지 실행 후 rax에 저장되는 값은?
0x401A48
산술 연산
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 |
퀴즈!
[Register]
rax = 0x31337
rbx = 0x555555554000
rcx = 0x2
=================================
[Memory]
0x555555554000| 0x0000000000000000
0x555555554008| 0x0000000000000001
0x555555554010| 0x0000000000000003
0x555555554018| 0x0000000000000005
0x555555554020| 0x000000000003133A
==================================
[Code]
1: add rax, [rbx+rcx*8]
2: add rcx, 2
3: sub rax, [rbx+rcx*8]
4: inc rax
- Code 1까지 실행 후 rax에 저장된 값?
0x3133A (rax의 값은 rbx+0x10(0x555555554010) 에 저장된 0x3 만큼 증가합니다.) - Code 3까지 실행 후 rax에 저장된 값?
0 (rax의 값은 rbx+0x20에 저장된 0x3133A 만큼 감소합니다.) - Code 4까지 실행 후 rax에 저장된 값?
1 (rax의 값은 1증가합니다.)
논리 연산 - and & or
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
퀴즈!
[Register]
rax = 0xffffffff00000000
rbx = 0x00000000ffffffff
rcx = 0x123456789abcdef0
==================================
[Code]
1: and rax, rcx
2: and rbx, rcx
3: or rax, rbx
- Code 1까지 실행 후, rax에 저장된 값?
0x1234567800000000 - Code 2까지 실행 후, rbx에 저장된 값?
0x000000009abcdef0 - Code 3까지 실행 후, rax에 저장된 값?
0x123456789abcdef0
논리 연산 - xor & not
xor dst, src: dst와 src의 비트가 서로 다르면 1, 같으면 0
[Register]
eax = 0xffffffff
ebx = 0xcafebabe
[Code]
xor eax, ebx
[Result]
eax = 0x35014541
not op: op의 비트 전부 반전
[Register]
eax = 0xffffffff
[Code]
not eax
[Result]
eax = 0x00000000
퀴즈!
[Register]
rax = 0x35014541
rbx = 0xdeadbeef
==================================
[Code]
1: xor rax, rbx
2: xor rax, rbx
3: not eax
- Code 1까지 실행 후 rax에 저장되는 값?
0xebacfbae - Code 2까지 실행 후 rax에 저장되는 값?
0x35014541 (xor연산을 동일한 값으로 두 번 실행할 경우, 원래 값으로 돌아감. XOR cipther 참고: https://en.wikipedia.org/wiki/XOR_cipher) - Code 3까지 실행 후 rax에 저장되는 값?
0xcafebabe (참고로 [Code]의 3번에서 rax가 아닌 eax를 not 해도 괜찮은 이유는 eax가 rax의 하위 32비트를 가리키는 부분이기 때문. 만약 not rax를 수행했다면 답은 0xffffffffcafebabe가 됨.)
비교
cmp op1, op2: op1과 op2를 빼서 대소 비교 후 같으면 ZF=1 -> 완전히 같은지 판단
cmp는 두 피연산자를 빼서 대소를 비교합니다. 연산의 결과는 op1에 대입하지 않습니다.
예를 들어, 서로 같은 두 수를 빼면 결과가 0이 되어 ZF플래그가 설정되는데, 이후에 CPU는 이 플래그를 보고 두 값이 같았는지 판단할 수 있습니다.
[Code]
1: mov rax, 0xA
2: mov rbx, 0xA
3: cmp rax, rbx ; ZF=1
test op1, op2: op1과 op2를 AND 비트연산 비교 후 모두 0 이면 ZF=1 -> 모두 0인지 판단
test는 두 피연산자에 AND 비트연산을 취합니다. 연산의 결과는 op1에 대입하지 않습니다.
예를 들어, 아래 코드에서 처럼 0이된 rax를 op1과 op2로 삼아 test를 수행하면, 결과가 0이므로 ZF플래그가 설정됩니다. 이후에 CPU는 이 플래그를 보고 rax가 0이었는지 판단할 수 있습니다.
[Code]
1: xor rax, rax
2: test rax, rax ; ZF=1
분기
- 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
요약
- 데이터 이동 연산자
- mov dst, src: src의 값을 dst에 대입
- lea dst, src: src의 유효 주소를 dst에 대입
- 산술 연산
- add dst, src: src의 값을 dst에 더함
- sub dst, src: src의 값을 dst에서 뺌
- inc op: op의 값을 1 더함
- dec op: op의 값을 1 뺌
- 논리 연산
- and dst, src: dst와 src가 모두 1이면 1, 아니면 0
- or dst, src: dst와 src중 한 쪽이라도 1이면 1, 아니면 0
- xor dst, src: dst와 src가 다르면 1, 같으면 0
- not op: op의 비트를 모두 반전
- 비교
- cmp op1, op2: op1에서 op2를 빼고 플래그를 설정
- test op1, op2: op1과 op2에 AND 연산을 하고, 플래그를 설정
- 분기
- jmp addr: addr로 rip 이동
- je addr: 직전 비교에서 두 피연산자의 값이 같을 경우 addr로 rip 이동
- jg addr: 직전 비교에서 두 피연산자 중 전자의 값이 더 클 경우 addr로 rip 이동
'study > 보안' 카테고리의 다른 글
x86 어셈블리 언어 - 주요 명령어 정리 (2) (0) | 2023.09.08 |
---|---|
x86 어셈블리 명령어(1) 리뷰 퀴즈 (0) | 2023.09.08 |
윈도우 메모리 구조 (0) | 2023.09.07 |
정적분석 vs 동적분석 (0) | 2023.09.07 |
Computer Architecture 컴퓨터 구조 (0) | 2023.09.07 |