명령어 집합 구조(Instruction Set Architacture; ISA)
명령어 집합 구조(ISA)는 하드웨어와 소프트웨어 간의 인터페이스 역할을 하며, CPU가 이해하고 실행할 수 있는 명령어들의 집합과 형식, 동작 방식을 정의한다.
명령어 집합 분류에는 CISC와 RISC가 있다. 아래의 표를 참고하자(내가 공부할 부분은 IA-32(x86)이기 때문에 CISC를 해볼 예정이다).

일반적인 명령은 Opcode(operation code)와 하나 이상의 Operand로 구성된다.
- Opcode - MOV 같은 명령어
- Operand - EIP와 같이 명령이 전달되는 인자(Opcode에 따라 Operand가 존재하지 않는 경우도 존재)
주소 지정 체계(Addressing Modes)
주소 지정 체계는 Opcode가 Operand의 위치를 지정하는 방법을 의미한다. 정의만으로는 감이 잘 오지 않을테니 주소 지정 체계의 종류를 간단하게 살펴보고, 예시를 통해 알아보자.
주소 지정 체계는 c언어의 변수, 상수, 포인터와 유사하다. addressing mode에는 크게 Register addressing, Immediate addressing, Memory addressing이 있다.
Register addressing(Reg)
- = 변수 = 레지스터 이름
- operand가 레지스터에 저장(적재)돼있는 값을 의미
- ex) EAX, EIP, ESP...
Immediate addressing(Imm)
- = 상수
- 메모리 접근 없이 상수 자체를 사용
- ex) 0x123456
Memory addressing(Mem)
- = 포인터
- Direct addressing
- [상수] 형태로 상수값이 가르키는 주소의 데이터를 의미
- [0x4A393D]
- Register Indirect addressing
- [변수] 형태로 변수 위치에 들어간 레지스터에 적재된 값이 가리키는 주소의 데이터를 의미
- [EAX]
- Based register addressing
- [Reg.base+Displacement] 형태로 레지스터에 저장된 값에 고정된 변위(offset, displacement)를 한 값이 가리키는 주소의 데이터
- [EAX+4h]
- Indexed addressing(추가)
- based-indexed addressing(추가)
instruction set은 일반적으로 다음과 같이 [opcode] [dest] [source] 형식으로 사용 가능하다.
(산술 연산의 경우 첫번째 피연산자에서 두번째 피연산자를 연산한다)

Instructions
데이터 전달(data movement instructions)
- MOV - 데이터를 복사
- LEA - 주소 계산식을 평가해, 결과 주소를 레지스터에 저장
- LEA EAX, [ECX] => ECX에 저장된 값이 가리키는 '메모리 주소'를 EAX에 복사
- PUSH/POP - 데이터를 스택에 push(저장)/pop(꺼내어 지정된 위치에 저장)
산술 연산(Arithmetic Instructions)
- INC/DEC - 피연산자 값을 1 증가/감소
- ADD - 두 피연산자 값을 더해 결과를 첫 번째 operand 저장
- SUB - 두 피연산자 간의 뺄셈
- SUB EAX, [ECX] => 뺄셈한 결과를 EAX에 저장
- destination - source
- MUL - 곱셈을 수행하고 값을 주로 AX, DX 등의 레지스터에 저장
- DIV - 나눗셈을 수행하고 몫과 나머지를 관련 레지스터에 저장
논리 연산(Logic and Shifting Instructions)
- AND, OR, XOR, NOT
- SHL/SAL - 비트를 왼쪽으로 이동시켜, 곱셈 효과를 내거나 비트 마스킹에 사용
- SHR/SAR - 비트를 오른쪽으로 이동시켜, 나눗셈 효과를 내거나 부호를 유지하면서 이동
비교 연산(Comparison Instructions)
- CMP - 두 피연산자를 비교, 결과에 따라 CPU의 조건 플래그(zero, sign, carry, overflow..)를 설정
- TEST - 두 피연산자 간의 비트별 AND 연산을 수행하지만, 결과를 저장하지 않고 플래그만 설정
- TEST BL, BL => BL이 0인지 확인(AND연산이기 때문에)
- 일반적으로 비교 연산 아래에 흐름 제어문이 온다
- 비교 연산이 끝나면 EFLAGS를 갱신한
흐름 제어(Jump and Conditional Jumps)
- JMP - 무조건 지정된 주소로 점프하여 프로그램 흐름 변경
- JE/JZ (Jump if Equal/Zero) - 비교 결과가 같거나, 결과가 0일 때 점프
- JNE/JNZ - 비교 결과가 같지 않거나, 0이 아닐 때 점프
- JL/JNGE, JLE/JNG, JG/JNLE, JGE/JNL
- LOOP - 반복 실행을 위해 카운터 레지스터(ECX, CX)를 사용해 루프 구현
함수 호출/종료(Function Related)
- CALL - 함수(서브루틴)를 호출하며, 현재 명령어 다음의 주소(복귀 주소)를 스택에 저장
- RET - 스택에 저장된 반환 주소로 점프하여 함수에서 복귀
EIP는 흐름 제어와 함수 호출/종료 명령문으로만 바꿀 수 있다!


N: not
Z: zero
E: equal
G: greater
L: less
O: overflow
P: partiy
C: carry
A: above(초과)
B: below(미만)
'정보보안 > Reversing' 카테고리의 다른 글
[Reversing] Calling Convention(호출 규약) (0) | 2025.04.07 |
---|---|
[Reversing] Memory Structure (0) | 2025.04.07 |
[Reversing] Register (0) | 2025.03.31 |
[Reversing] 데이터 구성 단위, Endian, 보수(Complement) (0) | 2025.03.31 |
[Reversing] 리버싱 전에 간단하게 공부하는 컴퓨터 구조 (0) | 2025.03.31 |