x86-64 어셈블리 명령
구성: 명령어 + 피연산자
피연산자에는 총 3가지 종류가 올 수 있다.
- 상수(Immediate Value)
- 레지스터(Register)
- 메모리(Memory)
1. 데이터 이동 🚚: mov (값), lea(주소)
2. 산술연산 ❌
3. 논리연산 🤔 - and & or
논리 연산 명령어는 and, or, xor, neg 등의 비트 연산을 지시한다. 이 연산은 비트 단위로 이루어 진다.
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
4. 논리연산 🤔 - 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
5. 비교 ⚖️ : cmp, test
cmp op1, op2: op1과 op2를 비교
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를 비교
test는 두 피연산자에 AND 비트연산을 취한다. 연산의 결과는 op1에 대입하지 않는다.
예를 들어, 아래 코드에서 처럼 0이된 rax를 op1과 op2로 삼아 test를 수행하면, 결과가 0이므로 ZF플래그가 설정된다.
이후에 CPU는 이 플래그를 보고 rax가 0이었는지 판단할 수 있다.
[Code]
1: xor rax, rax
2: test rax, rax ; ZF=1
6. 분기 🔀
분기 명령어는 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
출처
드림핵
'DreamHack > System Hacking' 카테고리의 다른 글
Background: x86-64 어셈블리 Pt.2 (0) | 2025.02.16 |
---|---|
Background: 레지스터 / 리눅스 메모리 구조 (0) | 2025.02.16 |