!단위 (암기좀 하자)
byte unit C
1 (b)yte char
2 (w)ord short
4 (d)word int, float, pointer, ...
8 (q)word long long,double..
10 (t)enbyte
1. 연산자
1). 사칙연산: +,-,*,/
[주소+] ->주소 표현 내에서만 사용이 가능하다
1-1). add 더하기
기본 사용법
ModRM:reg (r, w) ModRM:r/m (r)
값을 둘다 읽어서 더한값을 r 앞에 쓴다
올림수 처리를 생각해 줘야한다
ex)
extern printf
segment .data
prompt_int db '%d',10,00
a dd 10
b dd 20
segment .bss
segment .text
global main
main:
mov eax, dword [a] //메모리값[a]를 eax에 저장한다
add eax, dword [b] //메모리 값 [b]와 eax를 더해준다
push eax
push prompt_int
call printf
덧셈에 대한 결과값
1-2). sub 뺄셈
덧셈과 같은 방식으로 계산 해주면 된다
extern printf
segment .data
prompt_int db '%d',10,00
a dd 10
b dd 20
segment .bss
segment .text
global main
main:
mov eax, dword [a]
sub eax, dword [b]
push eax
push prompt_int
call printf
1-3).mul 곱하기
피 연산자의 비트에 따라서 계산하는 방식이 달라진다
레지스터 구조와 mul 계산 방식 두가지를 참고해야하는데
mul 계산 방식은 각 비트에 맞게 아래 설명이 잘나와있다.
레지스터 구조를 한번더 확인해보면
16비트 일때는 AH,AL로 나눠서 쓰는걸 볼수있다.
피연산자가 8비트 일때는
AX<-AL * r/m8
extern printf
AL에 메모리,레지스터 피연산자 8비트를 곱해서 AX(16비트) 에 저장한다
segment .data
prompt_int db '%d',10,00
a db 2
segment .bss
segment .text
global main
main:
mov eax, 0
mov al, 5
mul byte [a]
push eax
push prompt_int
call printf
정확하게 확인할려면 eax를 0으로 초기화하고 한다
피연산자가 16비트 인 경우에는
Unsigned multiply (DX:AX ← AX ∗ r/m16).
AX에 16비트를 곱하면 DX와 AX에 값이 나누어 저장된다.
9876 * 4500=4442000
=0000 0010 1010 0110 0010 0001 1001 0000
dx:678 0000 00010 1010 0110
ax:8592 0010 0001 1001 0000
extern printf
segment .data
prompt_int db '%d',10,00
prompt_int_int db '%d %d',10,10
a dw 9876
segment .bss
result resd 1
segment .text
global main
main:
mov eax,0
mov edx,0
mov ax, 4500
mul word [a]
push eax
push edx
push prompt_int_int
call printf
곱셈에 대한 결과값
imul(부호가 있는)
피연산자가 2개인 경우에는 add랑 동일
ModRM:reg (r, w) ModRM:r/m (r)
extern printf
segment .data
prompt_int db '%d',10,00
prompt_int_int db '%d %d',10,10
a dd 9876
segment .bss
segment .text
global main
main:
mov eax, 10
imul eax, dword [a]
push eax
push prompt_int
call printf
피연산자가 3개인 경우에는
ModRM:reg (r, w) ModRM:r/m (r) imm8/16/32
extern printf
segment .data
prompt_int db '%d',10,00
prompt_int_int db '%d %d',10,10
a dd 9876
segment .bss
segment .text
global main
main:
mov eax, 0
imul eax, dword [a], 10
push eax
push prompt_int
call printf
1-3).Div 나누기
div -> 4바이트 / 4바이트 = 2바이트
피연산자가 8비트 나눗셈
Unsigned divide AX by r/m8, with result
stored in AL ← Quotient, AH ← Remainder.
AX에 있는 값을 r/m8 비트로 나눠준다
몫은 AL 나머지는 AH에 저장한다
Unsigned divide AX by r/m8, with result
stored in AL ← Quotient, AH ← Remainder.
extern printf
segment .data
prompt_int db '%d',10,00
prompt_int_int db '%d %d',10,10
a db 7
segment .bss
segment .text
global main
main:
mov eax, 0
mov ax, 10
cwd ;convert word to byte
;cdw ;convert double word to word
;cdq ;convert double word to quad word
div byte [a]
push eax
push prompt_int
call printf
16비트 나눗셈은
Unsigned divide DX:AX by r/m16, with result
stored in AX ← Quotient, DX ← Remainder.
44442000 / 7412
=0000 0010 1010 0110 0010 0001 1001 0000
=dx:678, ax:8592
extern printf
segment .data
prompt_int db '%d',10,00
prompt_int_int db '%d %d',10,10
a dw 7412
segment .bss
segment .text
global main
main:
mov eax, 0
mov edx, 0
mov dx, 678
mov ax, 8592
cdw ;convert double word to word
div word [a]
push eax
push edx
push prompt_int_int
call printf
나눗셈 결과
idiv
2). 비교연산
3). 논리연산 : and, or, xor
1 and 0:0
1 or 0:1
xor 값을 초기화 할때 많이 쓴다
xor eax, eax
0으로 초기화 된다
4). 비트 연산: shift
-비트를 왼쪽/오른쪽으로 이동
곱셈
9876 * 4500=4442000
=0000 0010 1010 0110 0010 0001 1001 0000
dx:678 0000 0010 1010 0110
ax:8592 0010 0001 1001 0000
만약 dx를 왼쪽으로 16비트 이동하고
dx:0000 0010 1010 0110 0000 0000 0000 0000
ax:0000 0000 0000 0000 0010 0001 1001 0000
+ 더해주면
4442000:0000 0010 1010 0110 0010 0001 1001 0000 값이 출력된다
ax와 그 값을 합치면 곱셈을 하지 않아도 결과 값이 출력된다
명령어는 shl,shr
[root@korea /root]# vi basic.asm
extern printf
segment .data
prompt_int db '%d',10,00
prompt_int_int db '%d %d',10,10
a dw 9876
segment .bss
result resd 1
segment .text
global main
main:
mov eax,0
mov edx,0
mov ax, 4500
mul word [a]
mov dword [result], edx
shl dword [result], 16
add dword [result], eax
push dword [result]
push prompt_int
call printf
비트 연산을 할때는 부호를 생각해서 연산을 해주어야 한다.
extern printf
segment .data
prompt_int db '%d',10,00
prompt_int_int db '%d %d',10,10
a dw 9876
segment .bss
result resd 1
segment .text
global main
main:
xor edx, edx
mov dl, -2
shl dl, 2
shl dl, 2
push edx
push prompt_int
call printf
결과는 맞지않는 값이 출력된다
산술 시프트인 sar sal 을 이용해서 값을 구하면 정확한 값이 출력된다
extern printf
segment .data
prompt_int db '%d',10,00
prompt_int_int db '%d %d',10,10
a dw 9876
segment .bss
result resd 1
segment .text
global main
main:
xor edx, edx
mov edx, -2
sal edx, 2
sar edx, 2
push edx
push prompt_int
call printf
나눗셈
44442000 / 7412
=0000 0010 1010 0110 0010 0001 1001 0000
0000 0000 0000 0000 1111 1111 1111 1111 and
=dx:678, ax:8592
extern printf
segment .data
prompt_int db '%d',10,00
prompt_int_int db '%d %d',10,10
a dw 9876
segment .bss
result resd 1
segment .text
global main
main:
mov eax,0
mov edx,0
mov ax, 4500
mul word [a]
mov dword [result], edx
shl dword [result], 16
add dword [result], eax
push dword [result]
push prompt_int
call printf
mov edx, dword [result]
shr edx, 16
mov eax, dword[result]
and eax, 00000000000000001111111111111111b
;and eax, 0000ffffh
;and eax, 65535
cdw
div word [a]
push edx
push eax
push prompt_int_int
call printf
[실습]
-두 수를 입력 받아서 사칙연산 결과를 출력하는
어셈블리 프로그램 작성
-! 나눗셈은 몫과 나머지를 출력
- 최대로 받을수 있는 수는 int 형이니까 레지스터는 전부 eax,edx 등을 사용해서 계산하였다.
- 위에 기본을 배우려고 8비트 일 때16비트일 때 나누어서 생각했지만 일반적으로 계산할 때는 편의성을 위해 eax를 사용해서 32비트로 계산한다. 요즘 cpu가 이 정도 잡는다고 성능이 떨어지거나 하지 않기 때문이다
extern printf
extern scanf
segment .data
string1 db 'a+b:%d',10,00
string2 db 'a-b:%d',10,00
string3 db 'a*b:%d',10,00
string4 db 'a/b:%d %d',10,00
input dd '%d',00
segment .bss
a resd 4
b resd 4
segment .text
global main
main:
push a
push input
call scanf
push b
push input
call scanf
mov eax,0
mov eax, dword [a]
add eax, dword [b]
push eax
push string1
call printf
mov eax,0
mov eax,dword [a]
sub eax,dword [b]
push eax
push string2
call printf
mov eax,0
mov eax,dword [a]
mul dword [b]
push eax
push string3
call printf
mov eax,0
mov edx,0
mov eax,dword [a]
div dword [b]
push edx
push eax
push string4
call printf
'시스템 해킹' 카테고리의 다른 글
[시스템 해킹] 어셈블리 반복문 (0) | 2018.01.18 |
---|---|
[시스템 해킹] 어셈블리 형변환, 분기문 (0) | 2018.01.17 |
[시스템 해킹] 주소 Vs 메모리,레지스터 (0) | 2018.01.15 |
[시스템 해킹] 어셈블리 언어(레이블,변수)표현법 (0) | 2018.01.12 |
[시스템 해킹] Compile (0) | 2018.01.12 |