2017. 10. 18. 19:44ㆍSystemHacking/Assembly
1-1> 덧셈: ADD
1-2> 뺄셈: SUB
[ 덧셈 ]
[ 코드 설명 ]
main:
mov dword [sum], 10 ; sum = 10
add dword [sum], 20 ; sum = sum + 20
push dword [sum]
push argv1
call printf ; printf("%d",30)
뺄셈은 덧셈과 같은 형식으로 사용한다
1-3> 곱셈
MUL : unsigned(부호가 없는 연산)
# 부호 없는 al, ax, eax 레지스터 의 값을 피연산자와 곱한다
# 형식 : mul register|memory
# 원리
AL(8) * 8bit x/m -> AX ( 16bit )
AX(16) * 16bit x/m -> DX:AX ( 16bit 레지스터 2개를 사용한다 )
EAX(32) * 32bit x/m -> EDX:EAX ( 32bit 레지스터 2개를 사용한다
[ 곱셈 ]
main:
; 25 * 25 ( 8bit 상수 * 8bit 상수) = ax * ( 8bit register | memory )
mov eax, 0 ; eax레지스터 초기화
mov al, 25 ; al ( 8bit 레지스터 ) 에 25(8bit상수) 입력
mov dl, 25 ; dl ( 8bit 레지스터 ) 에 25(8bit상수) 입력
mul dl ; => al * dl
push eax ; push 는 32bit 해야함 ( push명령어의 특징 )
push argv1
call printf ; printf("%d",25*25) / * 8bit 끼리의 곱은 ax레지스터에 저장되어진다
[ 곱셈 심화 ]
[ 코드 설명 ]
main:
; 10000 * 10000 ; 16bit * 16bit => 16bit (dx) : 16bit (ax) 레지스터에 저장된다
mov eax, 0 ; eax 레지스터 초기화
mov edx, 0 ; edx 레지스터 초기화
mov ax, 10000 ; 16bit 레지스터 ax에 16bit 상수 10000 입력
mov dx, 10000 ; 16bit 레지스터 dx에 16bit 상수 10000 입력
mul dx ; ax의 10000 * dx의 10000 곱한다
push eax
push edx
push argv1
call printf ; printf("edx: %d , eax: %d", edx레지스터값 , eax레지스터값 )
16bit * 16bit 의 곱의 결과가 16bit로 표현할 수 없을 때 DX:AX 의 32bit형태로 표현한다
[ 곱셈 결과 ]
dx ( 상위 16bit ) : ax ( 하위 16bit )
결과를 보면 edx레지스터에 1525 , eax레지스터에는 57600 이 들어가 있다
edx register : 00000101 11110101
eax register : 11100001 00000000
edx register의 비트들은 상위 16비트이므로 " << 16bit shift " 연산해야한다
=> ex register의 값은 99942400 이 된다
결과적으로 두 레지스터의 합은 edx + eax = 1000000
* 참고로 16bit * 16bit 의 곱이 16bit로 표현할 수 있을 때에는 DX:AX 형식을 사용하지않고 AX에만 저장합니다
아래 그림은 AX register만 사용한 결과입니다
ax register 10000 , dx register 1 을 곱한 값으로 16bit의 상수가 출력되기 때문에 AX레지스터만 사용
1-4> 나눗셈
DIV ( unsigned )
# 형식 1
AX by DIV r/m8 : AX레지스터(16bit)의 값을 8비트 레지스터로 나눈다
AL에 몫, AH에 나머지
# 형식 2
DX:AX by DIV r/m16 : 32bit 레지스터 16bit로 나눈다
AX 에 몫 , DX에 나머지
[ 나눗셈 ]
[ 코드 설명 ]
main:
mov eax, 0 ; eax register 초기화
mov ax, 10 ; 16bit ax register에 상수 10 입력
mov dl, 4 ; 8bit dl register에 상수 4 입력
div dl ; 10/4 => 몫: 2, 나머지: 2
push eax
push eax
push argv1
call printf ; printf("%d %d", eax register 값, eax register 값 ) ; 귀찬아서 형식을 안바꿧음
[ 나눗셈 결과 ]
결과값으로 eax register에 514 상수가 들어가 있음을 확인할 수 있다
514 => 2진수 : 00000010 00000010
# 레지스터 저장 형태 ( AL에 몫, AH에는 나머지 값이 들어간다 )
00000010 |
00000010 |
AH |
AL |
[ 나머지 심화 ]
DX:AX by DIV r/m16 : 32bit 레지스터를 16bit로 나눈다 ( AX 에 몫 , DX에 나머지 )
* 곱셈을 공부할 때 32bit 상수는 16bit register 2개로 나눠서 표현한다고 공부했었다
원리에 대해서만 알아보고 다음 글에서 제대로 공부해보자 ( 복잡하다 .. )
1000000 => 00001111 01000010 01000000 : 16bit를 넘어섰다
# 1000000 이 상위 16bit DX register 와 하위 16bit AX register에 위치하는 형태
00000000 00001111 ( 15 ) |
01000010 01000000 ( 16960 |
DX |
AX |
DX:AX 레지스터에는 백만이라는 값이 들어가있는 것이다
DX:AX 레지스터의 값을 div 명령어를 이용해서 bx레지스터의 값으로 나누었다
[ 나눗셈 코드 설명 ]
mov dx, 15
mov ax, 16960
mov bx, 46
div bx ; 1000000 / 46
DX에는 나머지가 AX에는 몫이 들어간다
[ 출력 결과 ]
EAX : 21739
EDX : 6
'SystemHacking > Assembly' 카테고리의 다른 글
[6] 어셈블리 비트연산 ( shift, and, or, not ) (0) | 2017.10.20 |
---|---|
[5] 어셈블리 계산기 , scanf , printf (0) | 2017.10.19 |
[3] 어셈블리 text section / mov / lea (0) | 2017.10.17 |
[2] 어셈블리 문자열 표현방식 / 데이터단위 / 레지스터 종류 (0) | 2017.10.16 |
[1] 어셈블리 배경지식 / xxd, objdump 명령어 사용법 (0) | 2017.10.15 |