728x90
728x90
728x90
728x90

mov dest, src

src에 있는 데이터가 dest로 복사된다. 이때, 두 피연산자의 크기가 같아야 한다.

예를 들어, AX(16 비트)에 있는 값을 BL(8 비트)로 저장될 수 없다.
mov bx, ax : bx = ax

 

lea dst, addr

lea명령어는 Load Effective Address로, dst에 주소(addr)를 저장한다.

lea dst, addr : dst = addr

 

inc dst : dst값 1 증가

dec dst : dst값 1 감소
neg dst : dst = dst값의 부호 변경
not dst : dst = dst값 비트 반전

 

add dst, src : dst += src
sub dst, src : dst -= src
imul dst, src : dst *= src
and dst, src : dst &= src
or dst, src : dst |= src
xor dst, src : dst ^= src


shl dst, k : dst << k
shr dst, k : dst >> k
sal dst, k : dst << k 
sar dst, k : dst >> k

 

test dst, src

AND 논리 연산을 하지만, 결괏값을 피연산자에 저장하지 않는다.

test rax, rax : ZF=1 if rax = 0
                : SF=1 if rax < 0

test의 연산 결과는 FLAGS 레지스터에 저장된다. 두 피연산자의 AND 연산 결과가 음수이면(최상위 비트가 1이면) SF에 1을, 0이면 ZF에 1을 저장한다.

 

cmp dst, src

dst에서 src를 빼지만, 그 결괏값이 FLAGS 레지스터의 ZF와 CF 플래그에 영향을 미친다는 점에서 test와 유사하다.
dst=src일 때에는 ZF=1, CF=0이 되고, dst<src일 때에는 ZF=0, CF=1, 반대로 dst>src일 때에는 ZF=0, CF=0이 된다.

cmp rax, rdi : ZF=1 if rax = rdi
                : ZF=0 if rax != rdi
                : CF=1 if rax < rdi
                : CF=0 if rax > rdi

 

더보기

CF(Carry Flag) : 연산 수행하면서 자리올림(carry), 자리 내림(borrow) 발생하면 1이 된다.
                     unsigned 변수의 오퍼 플로우 발생 시 1로 세팅된다.
ZF(Zero Flag) : 연산 결과가 0이면 1로 세팅됨. if문 같은 조건문 만족 시 세팅된다.

PF(Parity Flag) : 패리티 체크하는 데 사용된다.
                     연산 결과 최하위 바이트의 값이 짝수일 경우에 1이 된다.
AF(Adjust Flag) : 연산결과 carry나 borrow가 3bit 이상 발생할 경우 1이 된다.
SF(Sign Flag) : 연산 결과 최상위 비트 값과 같다. Signed 변수일 경우, 양수이면 0, 음수이면 1이다.
OF(Overflow Flag) : Signed(부호 있는) 변수의 오버플로우가 발생했을 때, 1로 세팅된다. MSB(최상위 비트)가 변경될 때, 1로 세팅된다.
DF(Direction Flag) : 문자열 처리할 때, 1일 경우 문자열 처리 instruction이 자동으로 감소, 0일 경우 자동으로 증가한다.

 

jmp, jcc

jmp는 피연산자가 가리키는 곳으로 점프하는 명령어이다. jmp은 무조건 점프하고 jcc는 조건에 따라 점프를 한다는 차이가 있다. jcc는 명령어를 수행하기 전에 산술 연산을 하거나, test, cmp명령어로 바뀐 플래그를 바탕으로 점프의 수행 여부를 결정한다. jcc는 명령어가 아니라 je, jne, jg, jge, jl, jle 등 조건부 jmp를 묶어서 이르는 말이다.

jmp location
je location : equal (ZF=1)
jne location : not equal (ZF=0)
jg location : > signed
jge location : >= signed
jl location : < signed
jle location : <= signed
ja location : > unsigned
jb location : < unsigned
js location : negative (SF=1)
jns location : not negative (SF=0)

 

cmp dword ptr [rbp-0x2c], 0x47
jle   400a31

rbp 레지스터가 가리키는 주소에서 -0x2c만큼 떨어진 곳에 들어있는 값과 0x47을 비교하여, 이 값이 0x47보다 작거나 같으면(less or equal) 0x400a31로 점프한다.

 

push, pop

push와 pop 명령어는 스택에 새로운 데이터를 추가하거나 뺄 때 사용한다.

push rdi : sub rsp, 8
           : mov [rsp], rdi
스택에 새로운 데이터를 넣는 명령어는 push. 새로운 데이터가 들어가면 rsp 레지스터도 새로운 데이터가 들어간 주소를 가리켜야 하므로 rsp가 가리키는 주소에서 들어갈 데이터의 사이즈만큼 빼서 (sub rsp, 8) 데이터가 들어갈 크기를 확보한 뒤 데이터를 복사하는 과정(mov [rsp], rdi)과 동일하다.

 

pop rdi : mov rdi, [rsp]
           : add rsp, 8

pop은 push와 반대로 스택의 최상단에 있는 데이터를 빼내는 명령어이므로, 그 반대 순서로 진행하는 것과 동일한 효과이다.


참고문헌

 

 

728x90
728x90

'어셈블리어' 카테고리의 다른 글

어셈블리어 [2] 범용 레지스터  (0) 2021.11.16
어셈블리어 [1] 기초  (0) 2021.10.20
728x90
728x90

레지스터

cpu에서 연산을 위해 데이터를 일시적으로 저장하는 공간이며 영어로는 register로 등록/기록을 의미하는 영단어이다.

레지스트리와 이름이 비슷하다고 헷갈리지 말자

레지스트리는 OS의 설정 및 정보를 담고있는 데이터베이스이다.

레지스터의 종류에는

    범용 레지스터 : 임시 저장 공간이며 계산, 주소 지정 등의 목적으로 사용한다.

    포인터 레지스터 : 메모리 스택 영역과 관련된 주소 값을 저장한다.

    인덱스 레지스터 : 문자열 복사/비교와 관련된 레지스터이다.

    세그먼트 레지스터 : 다양한 크기로 구분을 하는 목적으로 사용되며 16bit로 구성된다.

    플래그 레지스터 : 실행 순서을 제어하기 위한 목적을 사용한다.

가 있다.

일단 범용 레지스터를 제외한 다른 레지스터들은 필요할 때 다시 포스팅 할 예정 사실 아직 안배웠음


범용 레지스터

범용 레지스터는 EAX, EBX, ECX, EDX 등이 있다. (32bit cpu 기준)

레지스터 EAX는 레지스터 AX(16bit)를 포함하고 AX다시 AH(8bit)와 AL(8bit)로 구성된다.

EBX 또한 BX로 구성되어 있고 BX는 BH와 BL로 구성되어 있다. ECX, EDX 또한 마찬가지

64bit의 경우 EAX를 포함하는 레지스터 RAX(64bit)가 있다. 여기서 R은 register의 R이며 EAX의 E는 extended의 E이다.

 

EAX에 16진법으로 표현된 값 "1234A6C8"이 저장된다면

AX에는 16진법으로 "A6C8"이 저장되고 AH에는 "A6" AL에는 "C8"이 저장된다.


용도

범용 레지스터는 용도를 정해두지 않고 다양하게 쓸 수 있는 레지스터입니다. x32의 범용 레지스터는 총 8개로 원칙적으로 용도가 정해져 있진 않지만, 관행적으로 그 쓰임새가 정해져 있는 경우도 있습니다.


참고문헌

인프런 - 유용한IT학습님의 어셈블리어 배우기

네이버 블로그 -  뽀구님의 어셈블리어 레지스터

hidaehyunlee님의 어셈블리 프로그램 구조와 x64 레지스터 이해하기

티스토리 블로그 - Wooeong's lab님의 리버싱 기초 지식 : 레지스터

 

728x90
728x90

'어셈블리어' 카테고리의 다른 글

어셈블리어 [3] 명령어 (Feat. 플래그 레지스터)  (0) 2021.12.08
어셈블리어 [1] 기초  (0) 2021.10.20
728x90
728x90

어셈블리어란

이진수로 구성된 기계어는 사람이 봤을 때는 알아보는 것이 불가능하기 때문에

이를 보완해서 나온 언어가 어셈블리어입니다.

어셈블리어는 기계어와 1:1로 대응되며 CPU에 따라 기계어가 다르기 때문에

어셈블리어 또한 CPU에 따라 다르게 작성해야 합니다.

 

NASM x86 어셈블리어로 구현한 'Hello, World!'

adosseg
.model small
.stack 100h

.data
hello_message db 'Hello, World!',0dh,0ah,'$'

.code
main proc
      mov    ax, @data
      mov    ds, ax

      mov    ah, 9
      mov    dx, offset hello_message
      int    21h

      mov    ax, 4C00h
      int    21h
main endp
end main


어셈블리어 기초 지식

1. CPU

메모리에 있는 내용을 읽고, 쓰고, 연산(사칙연산, 비교)을 하고 데이터를 메모리와 레지스터로 보냅니다.

하나의 CPU는 12~14개의 레지스터를 가지고 있으며

레지스터에는 범용 레지스터, 상태 레지스터, 플래그 레지스터 등이 있습니다.

 

2. 레지스터

레지스터는 CPU의 연산에 필요한 데이터를 일시적으로 저장하는 기억장치입니다.
32bit, 64bit 레지스터들이 있으며 레지스터 하나의 저장공간을 의미합니다

 

3. RAM

프로그램을 작동시키기 위해 필요한 정보를 저장하는 하드웨어
반도체로 조립된 셀의 집합이며 각각의 셀들은 주소가 있습니다.
프로그램에서 메모리는 RAM을 말합니다.


어셈블러의 종류

MASM - Windows
GAS - Linux/Unix
NASM - Windows, Linux, MAC
SASM - Wiondows, Linux


참고문헌

FU11M00N [어셈블리어] 어셈블리어란? 기초 이론

위키백과 어셈블리어

인프런 - 유용한IT학습님의 어셈블리어 배우기에서 배운 내용을 포스팅할 예정

728x90
728x90
728x90
728x90