[Assembly] Assembly - 1

EUGENE·2023년 4월 5일
0

어셈블리어란?

  • 컴퓨터(CPU)의 기계어와 치환되는 언어 ⚠️ CPU가 달라지면 어셈블리어도 달라진다!\

배경지식

  • CPU에 사용되는 명령어 집합 구조는 다양하다 📌 명령어 집합 구조 : ISA Instruction Set Architecture → 다양한 만큼 어셈블리어도 다양하다.

📌 내 컴퓨터의 환경은 x64아케텍처를 대상으로 하므로 x64만 어셈블리어를 다룬다

어셈블리어의 기본 구조

💡 명령어 + 피연산자
mov eax, 3 
; opcode operand1 operand2
; 대입해라 eax에 3을

명령어

개요

;데이터 이동
mov
lea

;산술 연산
inc
dec
add
sub

;논리 연산
and
or
xor
not

;비교
cmp
test

;분기
jmp, je, jg

;스택
push
pop

;프로시저(Prosedure)
call
ret
leave

;시스템 콜
syscall

; 강교수님 : 기타 등등 많으나 이것만 알아둬도 돼!
; 알아둬야 해

피연산자의 종류

  • 상수 ( Immediate Value )
  • 레지스터 ( Register )
  • 메모리 ( Memory ) 📌 메모리 피연산자는 [ 대괄호 ] 로 둘러쌓인 것으로 표현됨 앞에 크기 지정자(size directive) TYPE PTR 추가 TYPE
    1. BYTE

    2. WORD 워드, 2byte

    3. DWORD 더블 워드, 4byte

    4. QWORD 쿼터 워드, 8byte

      QWORD PTR [0x80488000] ; 0x80488000의 데이터를 8byte만큼 참조
      DWRD PTR [0x80488000] ; 0x80488000의 데이터를 4byte만큼 참조
      WORD PTR [rax] ; rax가 가리키는 주소에서 데이터를 2byte 만큼 참조

데이터의 이동

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

mov

src에 들어있는 값을 dst에 대입

mov dst, src ; src에 들어있는 값을 dst에 대입
; 순서 헷갈리지 말자! 도착지부터 적는거다.

mov rdi, rsi ; rsi의 값을 rdi에 대입
mov QWORD PTR[rdi], rsi ; rsi의 값을 rdi가 가리키는 주소에 대입
mov QWROD PTR[rdi+8*rcx], rsi ; rsi의 값을 rdi+8*rcx가 가리키는 주소에 대입

lea

src의 유효주소(Effective Address, EA)를 dst에 저장

lea dst, src ; src의 유효주소를 dst에 저장

lea rsi, [rbx+8*rcx] ; rbx+8*rcx를 rsi에 대입

산술 연산

add

dst에 src의 값을 더함

add dst, src ; dst에 src의 값을 더함

add eax, 3 ; eax += 3
add ax, WORD PTR[rdi] ; ax += *(WORD *)rdi

sub

dst에서 src의 값을 뺌

sub dst, src ; dst에서 src의 값을 뺌

sub eax, 3 ; eax -= 3
sub ax, WORD PTR[rdi] ; ax -= *(WORD *)rdi

inc

op의 값을 1 증가시킴

inc op ; op의 값을 1 증가시킴

inc eax ; eax += 1

dec

op의 값을 1 감소 시킴

dec op ; op의 값을 1 감소 시킴

dec eax ; eax -= 1

논리 연산

⚠️ 비트단위로 계산하는 거니까 16진수 → 2진수로 변환하여 계산해야함 귀찮음

and

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

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

;[Register]
eax = 0xffff0000
ebx = 0xcafebabe

;[Code]
and eax, ebx

;[Result]
eax = 0xcafe0000**

or

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

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

;[Register]
eax = 0xffff0000
ebx = 0xcafebabe

;[Code]
or eax, ebx

;[Result]
eax = 0xffffbabe ; 계산은 시간날때 해보세요**

xor

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

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

;[Register]
eax = 0xffffffff
ebx = 0xcafebabe

;[Code]
xor eax, ebx

;[Result]
eax = 0x35014541**

not

op의 비트 전부 반전

not op ; op의 비트 전부 반전

;[Register]
eax = 0xffffffff

;[Code]
not eax

;[Result]
eax = 0x00000000

비교

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

cmp

op1과 op2를 비교

cmp op1, op2 ; op1과 op2를 비교
; 대소를 비교하고 플래그만 세울뿐, 결과를 op1에 저장하지는 않음

;[Code]
1: mov rax, 0xA
2: mov rbx, 0xA
3: cmp rax, rbx ; ZF=1

test

op1과 op2를 비교

test op1, op2 ; op1과 op2를 비교
; AND연산 취함 결과는 op1에 대입 안함

;[Code]
1: xor rax, rax
2: test rax, rax ; ZF=1
; ZF플래그를 보고 rax가 0이였는지 판단

분기

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

⚠️ 분기문은 엄청 많지만 여백이 좁아 정리할 수 없다 고로 앞으로 알아가도록

jmp

addr로 rip를 이동시킴

📌 rip란?

프로세서가 읽고 있는 현재 명령의 위치를 가리키는 명령 포인터

jmp addr ; addr로 rip를 이동시킴

;[Code]
1: xor rax, rax
2: jmp 1 ; jump to 1

je

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

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

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

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

까먹을만한 거

  • 대괄호 안에 있으면 주소값이다
profile
한 줄로 소개하기엔 여백이 좁아 적지 않겠습니다.

0개의 댓글