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