1️⃣ X86 Assembly 기초
📜x86 아키텍처
- 데이터 타입 : 어셈블리 기본
- 주소 표기법 : 리틀 엔디안
- 레지스터 : 8개의 범용 레지스터, EIP, EFLAGS
- 호출규약 : cdecl, stdcall, fastcall
- 명령어 세트 : 가변 길이 명령어 형식을 사용
- 피연산자 : 레지스터, 메모리 주소, 주소값, 숫자
- 기본문법 : AT&T(add a,b > b=a+b) 또는 Intel (add a,b > a=a+b)
📜레지스터
- 8개의 범용 레지스터 + EIP(32비트)
- EFLAGS 레지스터(32비트)
- 세그먼트 레지스터(16비트)

- EAX(Extended Accumulator Register) : 산술 연산에 사용, 함수 리턴값 저장
- EBX(Extended Base Register) : 베이스, 특정 메모리를 가리키는 포인터
- ECX(Extended Count Register) : 카운터 코드에 사용 (흔히 for문 등의 카운터에 사용)
- EDX(Extended Data Register) : 데이터 레지스터 (곱셈, 나눗셈)
- ESI(Extended Source Index) : 문자열 연산의 출발지 포인터
- EDI(Extended Destionation Index) : 문자열 연산의 목적지 포인터 - ESP(Extended Stack Point) : 스택 포인터 - EBP(Extended Base Point) : 스택 프레임 베이스 포인터 .스택의 기준
- EIP(Extended Instruction Point) : 다음 실행할 명령어를 가리키는 포인터
📜EFLAGS 레지스터
- 상태 플래그
- 방향 플래그
- 시스템 & IOPL 플래그

- CF : Carry
- PF : Parity
- AF : Adjust
- ZF : Zero
- SF : Sign
- OF : Overflow
📜자주쓰는 명령어
명령어 유형 | 의미 | 대표 명령어 세트 |
---|---|---|
데이터 이동 | src에서 dst로 이동 | mov, lea, push, pop, les, pushad, popad |
산술 | 정수의 산술 연산 | add, adc, sub, sbb, mul, imul, div, idev, cmp, inc, dec |
부동 소수점 | 부동 소수점 산술 연산 | fadd, fsub, fmul, dic, cmp |
논리 | 비트 논리 연산 | adn, or, xor, not, shl/sal, shr, sar, ror, rol |
제어 이동 | 제어 흐름의 이동 | jmp, jcc, call, ret, int, into |
문자열 | 문자열의 비교, 이동 | movs, stos, sca, outs, rep, repz, repnz, repne |
I/O | 입력과 출력 | in, out |
변환 | 데이터 타입 변환 | movzx, movsx, cbw, cdq, bswap |
기타 | 플래그 조작, 특권 모드 처리 | clc, stc, cmc, std, cl, sti |
📜PUSH, POP
- PUSH : 스택에 데이터를 삽입 > push word/dword
> push 명령어는 자동으로 ESP를 4바이트 감소시킴
- POP : 스택에서 데이터를 꺼냄
> 스택에서 4바이트를 꺼내와 지정한 레지스터에 삽입
> POP 명령어는 자동으로 ESP를 4바이트 증가 시킴
📜MOV
- 레지스터 <-> 레지스터 (가능)
- 메모리 <-> 레지스터 (가능)
- Immediate 값(메모리가 아닌 명령어에 포함된 값) -> 레지스터 또는 메모리 (가능)
- 메모리 <-> 메모리 (불가능)
📜Assembly 프로그래밍 정상적으로 끝내는 방법
- mov eax, 1
mov ebx, 0
int 80h
>exit(0) 의 역할을 함
📜‘r/m32’ 주소형식
- 다음과 같은 형식을 가지는 문법을 의미 • mov eax, ebx ← ebx 에 담긴 내용을 eax 로 복사 • mov eax, [ebx] ← ebx에 담긴 내용이 가리키는 주소의 내용 (포인터 )을 eax 로 복사 • mov eax, [ebx+ecxX] ← ebx에서 ecxX 만큼 떨어진 곳에 위치한 주소의 내용을 eax 로 복사 • mov eax, [ebx + ecxX + Y] ← ebx에서 ecxX + Y 만큼 떨어진 곳에 위치한 주소의 내용을 eax 로 복사
📜ADD, SUB
- 목적지는 r/m32 또는 레지스터
- 출발지는 r/m32 또는 레지스터 또는 상수값
- 출발지와 목적지가 모두 r/m32일 수는 없음
- OF, SF, ZF, AF, PF, CF에 영향
📜LEA (복사, Load Effective Address - 유효주소 로드)
- 출발지는 r/m32
- 목적지는 레지스터
- 레지스터 연살 결과를 레지스터에 저장 (포인터 아님)
- MOV와 다른점
> MOV는 값을 로드함, mov eax, [ebp+esp+4] > [ebp+esp+4]의 주소가 가리키는 값을 로드함
> LEA는 유효 주소를 로드, lea eax, [ebp+esp+4] > [ebp+esp+4]의 주소를 로드함
📜AND
- 목적지는 r/m32 또는 레지스터
- 출발지는 r/m32 또는 레지스터 또는 상수값
- OF, CF, SF, ZF, PF
📜OR
- 목적지는 r/m32 또는 레지스터
- 출발지는 r/m32 또는 레지스터 또는 상수값
- OF, CF, SF, ZF, PF
📜XOR
- 목적지는 r/m32 또는 레지스터
- 출발지는 r/m32 또는 레지스터 또는 상수값
- OF, CF, SF, ZF, PF
📜INC
- 피연산자의 값을 1 증가시킴 > OF, SF, ZF, AF, PF에 영향
📜DEC
- 피연산자의 값을 1 감소시킴 > OF, SF, ZF, AF, PF에 영향
📜CMP(두 값을 비교)
- cmp 레지스터, 상수값
- cmp r/m32, 상수값
- cmp r/m32, 레지스터
- cmp 레지스터, r/m32
- 출발지에서 목적지 값을 뺀 결과를 플래그에 반영
- 결과는버림
📜TEST(논리비교)
- test eax, eax(eax 값이 0인 경우 ZF=1)
- 보통 jcc랑 같이 쓰임
📜제어흐름
- 조건부 제어 : IF, WHILE, SWITCH
- 비조건부 제어 : CALL, GOTO, EXCEPTION, INTERRUPT
📜JMP(jump)
- 피연산자 주소로 EIP를 변경
- Short Jump(OF 85) : 현재 EIP 값에서 -128~127 범위로 이동
- Far Jump(75) : 다른 세그먼트에 위치한 명령어로 이동
📜JCC (Jump if condition is met)
- 특정 조건을 만족할 경우 지정한 주소로 제어 흐름을 이동
- JNE : Jump Not Equal (ZF=0)
- JE : Jump Equal (ZF=1)
- JLE : Jump Less Equal (ZF=1 or SF<>OF)
📜CALL(함수 호출)
- call printf / 0x80480000 / [eax + 4]
- 우선 다음 실행할 명령어 주소를 스택에 삽입한 뒤 EIP에 해당 주소를 옮긴 뒤 이동하는 방식
- 외부 함수를 사용하는 경우 반드시 해당 함수가 포함된 라이브러리를 linker에 함께 전달해야 함
📜x86 함수 호출 규약
- cdecl
> x86 환경에서 대부분 C 컴파일러가 쓰는 규약
> Caller에서 스택을 정리
> 오른쪽에서 왼쪽 순서로 파라미터를 전달
> 항상 스택의 최상위에 함수의 첫 번째 파라미터가 위치
- stdcall
> MS가 자체적으로 만든 호출규약 (Win32 API에서 사용)
> 파라미터 입력 순서는 cdecl과 동일
> Callee가 스택을 정리
> 작고 빠른 프로그램에 용이
- 함수가 시작될 때, Callee가 Stack에 2가지 값을 저장
> EIP : caller의 next instruction (다시 돌아갔을때 실행할 명령어 위치)
> EBP : caller의 base pointer, main함수 시작부분 (다시 돌아갔을때 스택 프레임 기준)