본문 바로가기

Ping!_linux

3. x86 Assembly

 

ㅁ x64 어셈블리 언어

동사에 해당하는 명령어(Operation Code, Opcode)

목적어에 해당하는 피연산자(Operand)로 구성

x86-64 어셈블리어 문법 구조

명령어

명령 코드  
데이터 이동(Data Transfer) mov, lea
산술 연산(Arithmetic) inc, dec, add, sub
논리 연산(Logical) and, or, xor, not
비교(Comparison) cmp, test
분기(Branch) jmp, je, jg
스택(Stack) push, pop
프로시져(Procedure) call, ret, leave
시스템 콜(System call) syscall

 


피연산자

  • 상수(Immediate Value)
  • 레지스터(Register)
  • 메모리(Memory)

메모리 피연산자는 []으로 둘러싸인 것으로 표현됌

앞에 크기 지정자(Size Directive) TYPE PTR이 추가될 수 O. 

타입에는 BYTE, WORD, DWORD, QWORD가 올 수 있으며, 각각 1바이트, 2바이트, 4바이트, 8바이트의 크기를 지정

 

메모리 피연산자의 예

QWORD PTR [0x8048000] 0x8048000의 데이터를 8바이트만큼 참조
DWORD PTR [0x8048000] 0x8048000의 데이터를 4바이트만큼 참조
WORD PTR [rax] rax가 가르키는 주소에서 데이터를 2바이트 만큼 참조

 


+) 자료형 WORD의 크기가 2바이트인 이유

 

인텔은 WORD 자료형의 크기를 16비트로 유지했다. 왜냐하면, WORD 자료형의 크기를 변경하면 기존의 프로그램들이 새로운 아키텍처와 호환되지 않을 수 있기 때문

인텔은 기존에 사용하던 WORD의 크기를 그대로 유지하고, DWORD(Double Word, 32bit)와 QWORD(Quad Word, 64bit)자료형을 추가로 만듬


ㅁ 어셈블리 명령어

 

데이터 이동 

어떤 값을 레지스터나 메모리에 옮기도록 지시.

 

:: 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에 대입

 


산술 연산

 덧셈, 뺄셈, 곱셈, 나눗셈 연산 지시.

 

:: 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

 


 

논리 연산 - and & or

 

::  and dst, src: dst와 src의 비트가 모두 1이면 1, 아니면 0

 

::  or dst, src: dst와 src의 비트 중 하나라도 1이면 1, 아니면 0

 

논리 연산 - xor & not

::  xor dst, src: dst와 src의 비트가 서로 다르면 1, 같으면 0

 

:: not op: op의 비트 전부 반전


 

비교

: 두 피연산자의 값을 비교하고, 플래그를 설정

 


분기

: rip를 이동시켜 실행 흐름을 바꿈

-  jmp addr: addr로 rip를 이동시킨다.

-  je addr: 직전에 비교한 두 피연산자가 같으면 점프 (jump if equal)

-  jg addr: 직전에 비교한 두 연산자 중 전자가 더 크면 점프 (jump if greater)

 


스택

- push val: rsp를 8만큼 빼고, 스택의 최상단에 val을 쌓는다
- pop reg: 스택 최상단의 값을 reg에 넣고, rsp를 8만큼 더한다.

 

프로시저

- call addr: addr의 프로시저를 호출
- leave: 스택 프레임을 정리
- ret: 호출자의 실행 흐름으로 돌아김

 

시스템콜

syscall: 커널에게 필요한 동작을 요청

 

'Ping!_linux' 카테고리의 다른 글

Python 기초 문법 (2)  (3) 2024.03.16
Python 기초 문법 (1)  (1) 2024.03.15
기본 명령어 및 vi 에디터  (0) 2024.01.28
2. 리눅스 메모리 구조 (Linux Memory Layout)  (0) 2024.01.28
1. 컴퓨터구조  (0) 2024.01.28