시스템/리버싱
어셈블리 산술 연산 명령어
enable7997
2025. 6. 22. 14:57
반응형
산술 연산 명령
ADD 명령어 (add) | ||
ADD [피연산자1] [피연산자2] | ||
[피연산자1]에 [피연산자2]를 더하고 그 값을 저장하라 | ||
ADD EAX, 1 | ||
EAX에 1을 더한 값을 저장 |
SUB 명령어 (substract) | ||
SUB [피연산자1] [피연산자2] | ||
[피연산자1]에 [피연산자2]를 빼고 그 값을 저장하라 | ||
SUB EAX, 1 | ||
EAX에 1을 뺀 값을 저장 |
CMP 명령어 (compare) | ||
CMP [피연산자1] [피연산자2] | ||
[피연산자1]과 [피연산자2] 비교하고 두 값이 같은지 비교한다. [피연산자1]에 [피연산자2]를 빼고 그 값이 0이면 참이다. | ||
CMP EAX, 1 | ||
EAX와 1의 값이 같은지 비교한다. EAX-1이 0이라면 참이고 아니라면 거짓이다. |
ADC 명령어 (add with carry) | ||
ADC [피연산자1] [피연산자2] | ||
[피연산자1]에 [피연산자2]와 캐리를 포함하여 더하고 그 값을 저장하라 | ||
4비트 처리에 8비트를 처리하려면 상위 4비트와 하위 4비트로 나누어 저장하고 하위 4비트에서 연산하는데 이를 4비트가 저장할 수 있는 범위(2진수 1111, 10진수 15)를 넘어서면(자리올림) CF(캐리 플래그)가 1이 된다. | ||
ADC 9, 8 ; 4비트 환경이라고 가정할때 | ||
9는 2진수(0000 1001), 8은 2진수(0000 1000)이다. 4비트 환경 컴퓨터는 상위 4비트와 하위 4비트로 나누어 계산한다. 하위 4비트부터 ADD 연산을 하게 되고 계산값은 1001 + 1000 = (1) 0001으로 자리올림(CF) 1이 발생한다. 이후 상위 4비트를 더하는데 이전에 계산한 CF값도 포함하여 계산하면 0000 + 0000 + 1(CF) = 0001이 계산된다. 이제 상위 4비트와 하위 4비트를 합치면 0001 0001 (10진수 17)로 계산이 되는 것을 확인할 수 있다. |
SBB 명령어 ( subtraction with borrow) | ||
SBB [피연산자1] [피연산자2] | ||
[피연산자1]에 [피연산자2]를 캐리를 포함하여 빼고 그 값을 저장하라 | ||
4비트 처리에 8비트를 처리하려면 상위 4비트와 하위 4비트로 나누어 저장하고 하위 4비트에서 연산하는데 이를 4비트가 저장할 수 있는 범위(2진수 1111, 10진수 15)를 넘어서면(자리내림) CF(캐리 플래그)가 1이 된다. | ||
SBB 17, 9 ; 4비트 환경이라고 가정할때 | ||
17은 2진수(0001 0001), 9는 2진수(0000 1001)이다. 4비트 환경 컴퓨터는 상위 4비트와 하위 4비트로 나누어 계산한다. 하위 4비트를 계산하게 되면 0001 - 1001 = (1) 1000으로 1에서 9를 뺄 수 없으므로 자리내림(CF) 1이 발생하고 2의 보수 연산으로 1000이 계산된다. 이후 상위 4비트 계산하는데 이전에 계산한 CF를 포함하여 계산하면 0001 - 0000 - 1(CF) = 0000이 되는 것을 알 수 있다 이제 상위 4비트와 하위 4비트를 더하여 0000 1000 (10진수 8)로 계산되는 것을 알 수 있다. |
DEC 명령어 (decrement) | ||
DEC [피연산자1] | ||
[피연산자1] 값을 하나 1 감소시킨다. | ||
DEC EAX | ||
EAX 값을 1 감소시킨다. EAX의 값이 4라면 DEC EAX의 값은 3이 된다. |
NEG 명령어 (change sign) | ||
NEG [피연산자1] | ||
[피연산자1]의 값을 2의 보수 계산을 한다 / 부호를 반전시킨다. | ||
NEG EAX | ||
EAX의 값을 2의 보수 계산을 한다. 예시로 EAX의 값이 5라면 5의 2진수는 0000 0101이다. NEG EAX는 먼저 비트를 반전시키고 1111 1010, 다음에 1을 더하는 계산을 한다. 1111 1010 + 1 = 1111 1011 (10진수 -5) 계산값으로 컴퓨터가 인식하는 -5가 된다. |
INC 명령어 (increment) | ||
INC [피연산자1] | ||
[피연산자1]의 값을 1 증가시킨다. | ||
INC EAX | ||
EAX의 값을 1 증가시킨다. EAX가 4라면 INC EAX의 값은 5가 된다. |
PACK BSD, UNPACK BSD 차이 | ||
이진화 십진 코드(BCD)를 표현하는 두 가지 방식. 차이는 각 십진수를 표현하는데 필요한 비트 수 | ||
Packed BCD는 4비트(니블)를 사용하여 각 십진수를 표현하는 반면, unpacked BCD는 8비트(바이트)를 사용 | ||
특징 | Packed BSD | UnPacked BSD |
비트 수 | 4비트(니블) | 8비트(바이트) |
표현 예시(87) | 1000 0111 | 00001000 00000111 |
메모리 효율성 | 높음 | 낮음 |
구현 용이성 | 낮음 | 높음 |
사용 예시 | 데이터 저장 및 연산 | 입출력 |
AAA 명령어 (ASCII adjust for add) | ||
AAA | ||
비압축 BCD 덧셈값(unpacked BSD) 덧셈 결과의 AL 값을 UNPACK 10진수로 보정한다. | ||
덧셈 후 AL 레지스터의 값이 9를 초과하면, AL에는 십진수 단위(0~9)를 남기고 AH에 자리올림(1)을 더한다. mov ah, 0 ; AH를 0으로 초기화 mov al, 5 ; AL에 비압축 BCD 값 5를 저장 add al, 8 ; AL에 8을 더함 (AL = 13, 즉 0Dh(줄끝문자)) aaa ; 덧셈 결과 보정 ; 결과: AX = 0x0103 ; AH = 1 (자리올림), AL = 3 (단위) -> 즉, 십진수 13을 의미 |
AAS 명령어 (ASCII adjust for substract) | ||
AAS | ||
비압축 BCD 덧셈값(unpacked BSD) 뺄셈 결과의 AL 값을 UNPACK 10진수로 보정한다. | ||
비압축 BCD 뺄셈 후 결과를 보정한다. 뺄셈 시 자리내림이 발생하면 AL 값을 보정하고 AH에서 1을 뺀다. mov ah, 0 ; AH를 0으로 초기화 mov al, 3 ; AL에 3을 저장 sub al, 5 ; AL에서 5를 뺌 (AL = -2, 즉 0xFE(2진수 111111111 11111110), CF=1) aas ; 뺄셈 결과 보정 ; 결과: AX = 0xFF08 ; AH = -1 (자리내림), AL = 8 -> 십진수 연산에서의 자리내림을 표현 |
DAA 명령어 (decimal adjust for add) | ||
DAA | ||
압축 BCD(packed BCD) 덧셈 결과의 AL값을 PACK 10진수로 보정한다. | ||
AL의 각 4비트(니블)가 9를 초과하거나 자리올림이 발생하면 6을 더해 십진수 형식에 보정한다. mov al, 0x25 ; 압축 BCD 값 25를 AL에 저장 add al, 0x38 ; 38을 더함 (AL = 0x5D) daa ; 덧셈 결과 보정 ; AL의 하위 니블(D)이 9보다 크므로, AL에 6을 더함: 0x5D + 0x06 = 0x63 ; 결과: AL = 0x63 (십진수 63) |
DAS 명령어 (decimal adjust for substract) | ||
DAS | ||
압축 BCD(packed BCD) 뺄셈 결과의 AL값을 PACK 10진수로 보정한다. | ||
뺄셈 시 자리내림이 발생하면 AL에서 6을 빼서 십진수 형식에 맞춥니다. mov al, 0x52 ; 압축 BCD 값 52를 AL에 저장 sub al, 0x29 ; 29를 뺌 (AL = 0x29, CF=0, AF=1) -> 하위 니블에서 자리내림 발생 das ; 뺄셈 결과 보정 ; 하위 니블에서 자리내림(AF=1)이 발생했으므로, AL에서 6을 뺌: 0x29 - 0x06 = 0x23 ; 결과: AL = 0x23 (십진수 23) |
MUL 명령어 (multiply(unsigned) ) | ||
MUL [피연산자1] [피연산자2] ... | ||
부호 없는 정수의 곱셈을 수행한다. | ||
mov ax, 100 ; 피연산자1 (AX) mov bx, 200 ; 피연산자2 (BX) mul bx ; AX = AX * BX ; 결과: 32비트 결과가 DX:AX에 저장된다. ; 20000은 16진수로 0x4E20 이므로, ; DX = 0x0000, AX = 0x4E20이 된다. |
IMUL 명령어 (integer multiply(signed) ) | ||
IMUL [피연산자1] [피연산자2] [피연산자3] ... | ||
부호 있는 정수의 곱셈을 수행한다. | ||
; 예시: -10 * 20 = -200 mov bx, -10 ; 피연산자1 mov cx, 20 ; 피연산자2 imul ax, bx, 20 ; AX = BX * 20 ; 결과: AX = -200 (0xFF38) ; 다른 예시 (피연산자 1개) mov al, -5 mov bl, 10 imul bl ; AX = AL * BL = -50 (0xFFCE) |
AAM 명령어 (ASCII adjust for multiply) | ||
AAM | ||
두 비압축 BCD 값의 곱셈 후 AX에 저장된 이진수 결과를 두 개의 비압축 BCD 값으로 변환한다. AX를 10으로 나눈 몫을 AH에, 나머지를 AL에 저장합니다. |
||
; 예시 5 * 9 = 45 mov al, 5 mov bl, 9 mul bl ; AL * BL -> AX에 저장 (AX = 45, 즉 0x002D) aam ; 곱셈 결과 보정 ; AX를 10으로 나눔: 45 / 10 = 몫 4, 나머지 5 ; 결과: AX = 0x0405 ; AH = 4 (십의 자리), AL = 5 (일의 자리) |
AAD 명령어 (ASCII adjust for divide) | ||
AAD | ||
나눗셈 전에 두 자리 UNPACK BCD 값(AH, AL)을 하나의 이진수로 변환하여 AX에 저장한다. AX = AH * 10 + AL 연산을 수행한다. |
||
; 예시 십진수 72 나누기 mov ax, 0x0702 ; 두 자리 비압축 BCD 값 72 (AH=7, AL=2) aad ; 나눗셈 전 보정 ; AX = AH * 10 + AL = 7 * 10 + 2 = 72 (0x0048) ; 결과: AX = 0x0048, AH = 0x00, AL = 0x48 mov bl, 9 div bl ; 72 / 9 -> AL = 8 (몫), AH = 0 (나머지) |
DIV 명령어 (divide(unsigned)) | ||
DIV [피연산자1] | ||
부호 없는 정수의 나눗셈을 수행한다. | ||
; 예시 32비트 나눗셈 100000 / 300 mov dx, 1 ; 100000은 65535보다 크므로 DX:AX 사용 mov ax, 0x86A0 ; DX:AX = 0x000186A0 = 100000 mov cx, 300 ; 나눌 수 div cx ; DX:AX / CX ; 결과: ; AX = 몫 (100000 / 300 = 333 -> 0x014D) ; DX = 나머지 (100000 % 300 = 100 -> 0x0064) |
IDIV 명령어 (integer divide(signed)) | ||
IDIV [피연산자1] | ||
부호 있는 정수의 나눗셈을 수행한다. | ||
; 예시 -500 / 7 mov ax, -500 ; 나누어야 하는 수(-500은 0xFE0C) cwd ; AX의 부호를 DX로 확장 (DX = 0xFFFF) mov bx, 7 ; ax를 나눌 수 idiv bx ; DX:AX / BX ; 결과: ; AX = 몫 (-500 / 7 = -71 -> 0xFFB9) ; DX = 나머지 (-500 % 7 = -3 -> 0xFFFD) |
CBW 명령어 (convert byte to word) | ||
CBW | ||
AL 레지스터의 8비트 부호 있는 값(바이트)을 AX 레지스터의 16비트 값(워드)으로 부호 확장한다. AL의 최상위 비트(부호 비트)를 AH의 모든 비트에 복사한다. |
||
; 양수 확장 mov al, 100 ; AL = 100 (0x64), 부호 비트는 0 cbw ; AL의 부호를 AH로 확장 ; 결과: AX = 0x0064 (100) ; 음수 확장 mov al, -2 ; AL = -2 (0xFE), 부호 비트는 1 cbw ; AL의 부호를 AH로 확장 ; 결과: AX = 0xFFFE (-2) |
CWD 명령어 (convert byte to double word) | ||
CWD | ||
AX 레지스터의 16비트 부호 있는 값을 DX:AX의 32비트 값으로 부호 확장한다. AX의 최상위 비트(부호 비트)를 DX의 모든 비트에 복사한다. IDIV 전에 나누어야 할 값을 준비하는 데 필수적 |
||
; 양수 확장 mov ax, 5000 ; AX = 5000 (0x1388), 부호 비트는 0 cwd ; AX의 부호를 DX로 확장 ; 결과: DX = 0x0000, AX = 0x1388 ; 음수 확장 mov ax, -5000 ; AX = -5000 (0xEC78), 부호 비트는 1 cwd ; AX의 부호를 DX로 확장 ; 결과: DX = 0xFFFF, AX = 0xEC78 |
반응형