Computer Security

#2 어셈블리어 연산,비교,분기 본문

컴퓨터구조&어셈블리어

#2 어셈블리어 연산,비교,분기

쿠리 Kuri 2022. 5. 12. 18:30

 

코드 <--> 어셈블리어 <--> 기계어 

위와 같이 어셈블리어는 우리가 친 코드를 기계어로 치환해주는 역할을 수행한다.

 

어셈블리어는 명령어(Operation Code,Opcode)와 목적어에 해당하는 피연산자(Operand)로 구성된다.

 

인텔x64매우 많은 명령어가 존재하는데,

중요한 21개의 명령어를 살펴보자.

 

데이터 이동(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

 


피연산자에는 총 3가지 종류가 올 수있다.

1.상수(Immediate Value)

2.레지스터(Register)

3.메모리(Memory)

 

메모리 피연산자는 []로 둘러싸인 것으로 표현되고, 앞에 크기 지정자(Size Directive) TYPE PTR이 추가될 수 있다.

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

 

메모리 피연산자 예시)

QWORD PTR[0x8048000]  : 0x8048000의 데이터를 8바이트만큼 참조

DWORD PTR[0x8048000]  : 0x8048000의 데이터를 4바이트만큼 참조

WORD PTR[rax] : rax가 가리키는 주소에서 데이터를 2바이트 만큼 참조


 

데이터의 이동

 

mov dst,src : src에 들어있는 값을 dst에 대입

 

mov rdi,rsi : rsi의 값을 rdi에 대입

mov QWRD PTR[rdi],rsi : rsi의 값을 rdi가 가리키는 주소에 대입

mov QWRD 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에 대입

 

코드예시

[Register]
rbx = 0x401A40
=================================
[Memory]
0x401a40 | 0x0000000012345678
0x401a48 | 0x0000000000C0FFEE
0x401a50 | 0x00000000DEADBEEF
0x401a58 | 0x00000000CAFEBABE
0x401a60 | 0x0000000087654321
=================================
[Code]
1: mov rax, [rbx+8]
2: lea rax, [rbx+8]

위를 보면

1번: "값"을 대입 하는 것이기 때문에, rbx+8 같은경우 0x401a40 에서 +8 인  0x401a48의 값을 

넣어주므로,  답은 :  0x0000000000C0FFEE 이 된다.

2번: "주소"를 대입 하는 것이기 때문에, 0x401A40 에서 8을 더한 0x401A48이 그대로 대입된다.

 


산술 연산

 

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

 

[Register]
eax = 0xffff0000
ebx = 0xcafebabe
[Code]
and eax, ebx
[Result]
eax = 0xcafe0000

 

 

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

 

[Register]
eax = 0xffff0000
ebx = 0xcafebabe
[Code]
or eax, ebx
[Result]
eax = 0xffffbabe

 

 

논리 연산 - xor&not

 

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

 

[Register]
eax = 0xffffffff
ebx = 0xcafebabe
[Code]
xor eax, ebx
[Result]
eax = 0x35014541

 

not op: op의 비트 전부 반전

 

[Register]
eax = 0xffffffff
[Code]
not eax
[Result]
eax = 0x00000000

 

 

비교

 

비교 명령어는 두 피연산자의 값을 비교하고, 플래그를 설정한다.

 

cmp op1, op2: op1과 op2를 비교

cmp는 두 피연산자를 빼서 대소를 비교한다.

연산의 결과는 op1에 대입하지 않는다.

예를 들어, 서로 같은 두 수를 빼면 결과가 0이 되어 ZF플래그가 설정되는데, 이후에 CPU는 이 플래그를 보고 두 값이 같았는지 판단할 수 있다.

 

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

 

test op1, op2: op1과 op2를 비교

 

test는 두 피연산자에 AND 비트연산을 취한다.

연산의 결과는 op1에 대입하지 않는다.

예를 들어, 아래 코드에서 처럼 0이된 rax를 op1과 op2로 삼아 test를 수행하면, 결과가 0이므로 ZF플래그가 설정된다.

이후에 CPU는 이 플래그를 보고 rax가 0이었는지 판단할 수 있다.

 

[Code]
1: xor rax, rax
2: test rax, rax ; ZF=1

 

 

분기

 

분기 명령어는 rip를 이동시켜 실행 흐름을 바꾼다.

 

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

 

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

 

je addr : 직전에 비교한 두 피연산자가 같으면 점프한다.

 

[Code]
1: mov rax, 0xcafebabe
2: mov rbx, 0xcafebabe
3: cmp rax, rbx ; rax == rbx
4: je 1 ; jump to 1

 

jg addr: 직전에 비교한 두 연산자 중 전자가 더 크면 점프한다.

 

[Code]
1: mov rax, 0x31337
2: mov rbx, 0x13337
3: cmp rax, rbx ; rax > rbx
4: jg 1  ; jump to 1

'컴퓨터구조&어셈블리어' 카테고리의 다른 글

#6 컴퓨터구조와 명령어  (0) 2022.05.16
#5 컴퓨터 구조2  (0) 2022.05.15
#4 컴퓨터 구조1  (0) 2022.05.14
#3 어셈블리어 스택  (0) 2022.05.13
#1 프로세스의 메모리 구조. 세그먼트(Segment)  (0) 2022.05.11
Comments