어셈블러는 일종의 통역사인데, 개발자들이 어셈블리어로 코드를 작성하면 컴퓨터가 이해할 수 있는 기계어로 코드를 치환해줬습니다.
어셈블리 언어
컴퓨터의 기계어와 치환되는 언어입니다. 이는 기계어가 여러 종류라면 어셈블리어도 여러 종류여야 함을 의미합니다. 그리고 앞에서 명령어 집합 구조를 설명할 때 cpu에 사용되는 ISA는 종류가 굉장히 다양합니다.
따라서 이들의 종류만큼 많은 수의 어셈블리어가 존재합니다.
x64 어셈블리 언어
어셈블리 언어는 명령어(Operation Code), **피연산자(Operand)**로 구성됩니다.
명령어
피연산자
피연산자는 총 3가지 종류가 올 수 있습니다.
- 상수
- 레지스터
- 메모리
메모리 피연산자는 []으로 둘러싸인 것으로 표현되며 앞에 크기 지정자(Size Directive) TYPE PTR이 추가될 수 있습니다. 여기서 BYTE, WORD, DWORD, QWORD가 올 수 있으며, 각 1바이트, 2바이트 4바이트 , 8바이트의 크기를 지정합니다.
데이터 이동
데이터 이동 명령어는 어떤 값을 레지스터나 메모리에 옮기도록 지시합니다.
lea 명령어는 주소를 대입한다.
유효 주소를 rsi에 저장합니다.
유효 주소란 컴퓨터에서 명령어가 여러 가지 레지스터로 표현되어 실행될 때, 연산이 끝난 후 최종적으로 피연산자가 있는 곳을 가리키는 주소
lea rsi, [rbx+8*rcx] //rbx+8*rcx 를 rsi에 대입
산술 연산
add ax, WORD PTR[rdi] // ax+*(WORD *)rdi 꼭 기억하자!
논리 연산
[Register] eax = 0xffff0000 ebx = 0xcafebabe
[Code] and eax, ebx
[Result] eax = 0xcafe0000
비교
두 피연산자의 값을 비교하고, 플래그를 설정합니다.
cmp는 두 피연산자를 빼서 대소를 비교합니다. 예를 들어 서로 같은 두 수를 빼면 결과가 0이 되어 ZF플래그가 설정되는데, 이후에 CPU는 이 플래그를 보고 두 값이 같았는지 판단할 수 있습니다.
TEST는 두 피연산자에 AND 비트 연산을 취합니다.
예를 들어 아래 코드에서 처럼 0이 된 rax를 op1과 op2로 삼아 test를 수행하면 결과가 0이므로 ZF플래그가 설정됩니다. 이후에 CPU는 이 플래그를 보고 rax가 0이었는지 판단할 수 있습니다.
[Code]
1: xor rax, rax
2: test rax, rax ; ZF=1
'Dreamhack - Reverse Engineering' 카테고리의 다른 글
Exercise: Helloworld (0) | 2022.02.18 |
---|---|
x86 Assembly🤖: Essential Part(2) (0) | 2022.02.18 |
Windows Memory Layout (0) | 2022.02.18 |
Background: Computer Architecture (0) | 2022.02.18 |
드림핵 리버싱 (0) | 2022.02.18 |