Prince of Songkla University



Chapter 5

Arithmetic Instructions

5.1 Introduction

5.1.1 Processing unsigned and signed data

For unsigned data, where all bits are intended to be data bits, a 16-bit register can contain a maximum of 65,535. For signed data, where the leftmost bit is a sign bit, the register can contain a maximum of 32,767. But note that the ADD and SUB instructions do not distinguish between unsigned and signed data and, indeed, simply add and subtract bits.

Example,

a) no carry or overflow

unsigned signed

binary decimal decimal OF CF

11111001 249 -7

+ 00000010 2 +2

11111011 251 -5 0 0

b) arithmetic carry

unsigned signed

binary decimal decimal OF CF

11111100 252 -4

+ 00000101 5 +5

(1)00000001 1 +1 0 1

(invalid) (valid)

c) overflow

unsigned signed

binary decimal decimal OF CF

01111001 121 +121

+ 00001011 11 +11

10000100 132 -124 1 0

(valid) (invalid)

d) carry and overflow

unsigned signed

binary decimal decimal OF CF

11110110 246 -10

+ 10001001 137 -119

(1)01111111 127 +127 1 1

(invalid) (invalid)

5.1.2 Data in decimal format

The 8086/8088 also supports Binary-Coded Decimal (BCD) format. A BCD digit consists of four bits that represent the decimal digits 0 through 9:

Binary BCD digit Binary BCD digit

0000 0 0101 5

0001 1 0110 6

0010 2 0111 7

0011 3 1000 8

0100 4 1001 9

You can store BCD digits as unpacked or as packed:

( Unpacked BCD contains a single BCD digit in the lower (rightmost) four bits of each byte, with zeros in the upper four bits. Note that althrough ASCII format is also in a sense “unpacked,” it isn’t called that.

( Packed BCD contains two BCD digits, one in the upper four bits and one in the lower four bits.

Example, Let’s examine the representation of the decimal number 1,527 in the three decimal formats:

Format Contents Length

ASCII 31h 35h 32h 37 h 4 bytes

Unpacked BCD 01h 05h 02h 07h 4 bytes

Packed BCD 15h 27h 2 bytes

Note!

- processing ASCII and unpacked BCD see AAA for addition, AAS for subtraction

- processing unpacked BCD data see AAM for multiplication, AAD for division

- processing packed BCD data see DAA for addition, DAS for subtraction

5.2 Arithmetic Instructions

mnemonic assembler format flags

OF DF IF TF SF ZF AF PF CF

Addition

add add destination,source * - - - * * * * *

adc adc destination,source * - - - * * * * *

aaa aaa ? - - - ? ? * ? *

daa daa ? - - - * * * * *

inc inc destination * - - - * * * * -

Subtraction

sub sub destination,source * - - - * * * * *

sbb sbb destination,source * - - - * * * * *

aas aas ? - - - ? ? * ? *

das das ? - - - * * * * *

dec dec destination * - - - * * * * -

neg neg destination * - - - * * * * *

cmp cmp destination,source * - - - * * * * *

Multiplication

mul mul source * - - - ? ? ? ? *

imul imul source * - - - ? ? ? ? *

aam aam ? - - - * * ? * ?

Division

div div source ? - - - ? ? ? ? ?

idiv idiv source ? - - - ? ? ? ? ?

aad aad ? - - - * * ? * ?

Sign-Extension

cbw cbw - - - - - - - - -

cwd cwd - - - - - - - - -

Note! * means changed, – means unchanged, and ? means undefined

5.2.1 Addition

ADD : Add Binary Numbers

Operation. Adds binary values from memory, register, or immediate to a register, or adds values in a register or immediate to memory. Values may be byte or word.

Note! มีผลกับค่า flags ดังนี้

- CF มีค่า 0 ถ้าผลลัพธ์ไม่มีการทดค่า

มีค่า 1 ถ้าผลลัพธ์มีการทดค่า

- PF มีค่า 0 ถ้าผลลัพธ์มีจำนวนบิตที่มีค่า 1 เป็นคี่

มีค่า 1 ถ้าผลลัพธ์มีจำนวนบิตที่มีค่า 1 เป็นคู่

- AF มีค่า 0 ถ้าผลการบวกเลขฐานสิบไม่ต้องปรับค่า (พิจารณาเฉพาะการทดค่าจากบิต 3 ไป 4 ของ AL)

มีค่า 1 ถ้าผลการบวกเลขฐานสิบต้องปรับค่า (พิจารณาเฉพาะการทดค่าจากบิต 3 ไป 4 ของ AL)

- ZF มีค่า 0 ถ้าผลลัพธ์ไม่ใช่ 0

มีค่า 1 ถ้าผลลัพธ์เป็น 0

- SF มีค่า 0 ถ้าผลลัพธ์มีค่าบวก

มีค่า 1 ถ้าผลลัพธ์มีค่าลบ

- OF มีค่า 1 ถ้าเป็นการบวกเลขที่ sign bit เหมือนกัน แต่ให้ผลลัพธ์ที่มี sign bit เปลี่ยนไป มิฉะนั้นจะมีค่าเป็น 0

Source Code. ADD {register/memory},{register/memory/immediate}

Object Code. (three formats)

Reg/mem with reg: |000000dw|modregr/m|

Immed to accumu’r: |0000010w|---data---|data if w=1|

Immed to reg/mem: |100000sw|mod000r/m|---data---|data if sw=01|

ตัวอย่าง พิจารณาการบวกเลขฐาน 2 ต่อไปนี้

; AL = 01110011 = 115 decimal

; BL = 00010010 = 18 decimal

add al,bl ; al เก็บผลลัพธ์ = 10000101 , bl unchanged

;CF = 0, AF = 0, ZF = 0, SF = 1, OF = 1, PF = 0

sign bit ; unsigned addition valid signed addition invalid

bit 7654 3210

AL 0111 0011 operands have the same sign (i.e. 0)

BL 0001 0010 sign bit changed (from 0 to 1) OF = 1

AL 1000 0101 # of 1 is odd PF = 0, bit 7 is 1 so SF =1, result ( 0 so ZF = 0

0. 0

CF AF

คำสั่ง ADD จะบวกเลขฐาน 2 ดังกล่าวข้างต้นเสมอ ท่านผู้ซึ่งเป็นคนเขียนโปรแกรมต้องตีความเองว่า ท่านกำลังบวกเลขที่มีเครื่องหมายหรือไม่มีเครื่องหมาย ถ้าท่านบวกเลขที่มีเครื่องหมาย ท่านจะตรวจสอบว่าผลลัพธ์ overflow ได้โดยตรวจสอบจาก OF = 1 ได้ เช่น ตัวอย่างข้างต้น (+115) + (+18) = +133 ซึ่งมีค่าเกิน +127 ซึ่งถ้าดูจากผลลัพธ์แล้ว 1000 0101 มีค่าเท่ากับ –123 ซึ่งไม่ถูกต้อง แต่ถ้าท่านบวกเลขที่ไม่มีเครื่องหมาย ท่านจะตรวจสอบว่าผลลัพธ์ overflow ได้โดยตรวจสอบจาก OF = 1 ไม่ได้ เพราะถ้าดูจากตัวอย่างข้างต้น 115 + 18 = 133 ซึ่งมีค่าไม่เกิน 255 ซึ่งถ้าดูจากผลลัพธ์แล้ว 1000 0101 มีค่าเท่ากับ 133 ซึ่งถูกต้อง การตรวจสอบว่าการบวกเลขที่ไม่มีเครื่องหมายเกิด overflow หรือไม่ให้ดูที่ CF = 1 หรือไม่ เช่น

; AL = 11111111 , unsigned = 255 decimal, signed = -1

; BL = 00000001 , unsigned = 1 decimal , signed = +1 decimal

add al,bl ; al เก็บผลลัพธ์ = 00000000 , bl unchanged

;CF = 1, AF = 1, ZF = 1, SF = 0, OF = 0, PF = 1

; unsigned addition invalid signed addition valid

sign bit

bit 7654 3210

AL 1111 1111 operands have the different sign OF = 0

BL 0000 0001

AL 0000 0000 # of 1 is even PF = 1, bit 7 is 0 so SF =0, result = 0 so ZF = 1

1. 1

CF AF

ADC : Add with Carry

Operation. Typically used in multiword binary addition to carry an overflowed 1-bit into the next stage of arithmetic. If the CF flag is set, ADC first adds 1 to operand 1. ADC then adds operand 2 to operand 1, just as ADD does.

Source Code. ADC {register/memory},{register/memory/immediate}

Object Code. (three formats)

Reg/mem with reg: |000100dw|modregr/m|

Immed to accumu’r: |0001010w|---data---|data if w=1|

Immed to reg/mem: |100000sw|mod010r/m|---data---|data if sw=01|

หมายเหตุ เหมือน ADD แต่บวก carry flag(CF) ด้วย คือ destination = destination + carry + source

ตัวอย่าง

add ax,cx

adc bx,dx

ADC BX,DX ADD AX,CX

CF

BX AX

DX CX

BX AX

ตัวอย่าง

; 32 bits integer addition

; z = x+y

dosseg

.model small

.stack 1024

.data

x dd 12345678h

y dd 9abcdef0h

z dd ?

.code

start:

mov ax,@data

mov ds,ax

mov ax,word ptr x

add ax,word ptr y

mov word ptr z,ax

mov ax,word ptr x+2

adc ax,word ptr y+2

mov word ptr z+2,ax

mov ax,4c00h

int 21h

end start

AAA : ASCII Adjust for Addition

Operation. Corrects the sum of two ASCII bytes in the AL. If the rightmost four bits of the AL have a value greater than 9 or if the AF flag is set to 1, AAA adds 1 to the AH and sets the AF and CF flags. Otherwise, the AF and CF are cleared. AAA always clears the leftmost four bits of the AL.

Source Code. AAA

Object Code. 00110111

สมมุติว่าเราต้องการบวกตัวเลข ASCII 8 (38H) และ 4 (34H)

0011 1000 (ASCII 38H)

+ (ใช้คำสั่ง ADD)

0011 0100 (ASCII 34H)

0110 1100 (6CH)

จะเห็นได้ว่าผลลัพธ์ที่ได้ไม่เป็นไปตามที่เราคาดหวัง เราคาดหวังว่าจะได้ ASCII 1 (31H) ASCII 2 (32H) หรือ 12 (3132H) คำสั่ง AAA และ OR (จะกล่าวในบทถัดไป) จะช่วยเราในเรื่องนี้

คำสั่ง AAA ไม่มี operand ใช้เพื่อปรับค่าในเรจิสเตอร์ AX เท่านั้น โดยการพิจารณาค่า 4 บิตล่างของ AL ถ้ามีค่าระหว่าง 0-9 ก็จะทำให้ 4 บิตบนของ AL มีค่าเป็น 0 และกำหนดให้ AF กับ CF มีค่าเป็น 0 แต่ถ้า 4 บิตล่างของ AL มีค่ามากกว่า 9 หรือ AF มีค่า 1 จะมีวิธีการปรับค่า ดังนี้

- บวก 6 กับเรจิสเตอร์ AL เลข 6 มาจาก 16 (hexadecimal) – 10 (decimal)

- บวก 1 กับเรจิสเตอร์ AH

- กำหนดให้ AF = 1 และ CF = 1

- 4 บิตบนของเรจิสเตอร์ AL มีค่า 0

หมายเหตุ ถ้าต้องการเก็บตัวทดใน AH ก่อนใช้คำสั่ง AAA ทำ AH ให้เป็น 0 แล้วใช้คำสั่งบวกที่มี AL เป็น destination ก่อน

ตัวอย่าง

a)

; AH = 0 AL = 34H (ASCII 4)

; BL = 38H (ASCII 8)

MOV AX,0034H ; AH = 0, AL = 34H

MOV BL,38H

ADD AL,BL ; add 34H with 38H, AX equals 006CH

AAA ; เนื่องจาก 4 บิตล่างของ AL มีค่ามากกว่า 9 บวก 6 กับ AL บวก 1 กับ AH

; กำหนดให้ CF = 1 และ AF = 1 แล้วทำให้ 4 บิตบนของ AL มีค่าเท่ากับ 0

; ผลสุดท้าย AX = 0102H

b)

; AL = 39H (ASCII 9)

MOV AX,0039H ; AH = 0, AL = 39H

ADD AL,AL ; add 39H with 39H, AX equals 0072H, AF = 1

AAA ; เนื่อง AF = 1 แม้ค่าจาก 4 บิตล่างของ AL มีค่าน้อยกว่า 9 บวก 6 กับ AL

; บวก 1 กับ AH

; กำหนดให้ CF = 1 และ AF = 1 แล้วทำให้ 4 บิตบนของ AL มีค่าเท่ากับ 0

; ผลสุดท้าย AX = 0108H

จะเห็นได้ว่าทั้งสองตัวอย่างข้างต้น ยังไม่ได้ค่า 3132H หรือ 3138H ตามที่เราต้องการ จะต้องใช้คำสั่ง

OR AX,3030H จึงจะได้ค่าตามที่ต้องการ ดังนั้นชื่อของ AAA (ASCII Adjust for Addition) ที่ใช้ อาจจะทำให้เข้าใจผิดได้ง่าย จริง ๆ แล้วคำสั่ง AAA เป็นแค่การปรับค่าของการบวก Unpacked BCD เท่านั้น น่าจะมีชื่อเป็น Unpacked BCD Adjust for Addition

สรุปแล้ว AAA ใช้ได้ทั้งการปรับค่าของการบวก ASCII และ Unpacked BCD แต่ถ้าเป็นการบวกของ ASCII และต้องการให้ผลลัพธ์เก็บอยู่ในรูป ASCII ต้องใช้คำสั่ง OR AX,3030H เพิ่มอีกคำสั่งหนึ่ง

DAA : Decimal Adjust for Addition

Operation. Corrects the result of adding two BCD (packed decimal) items in the AL. If the rightmost four bits have a value greater than 9 or the AF flag is 1, DAA adds 6 to the AL and sets the AF. If the leftmost four bits have a value greater than 9 or the CF flag is 1, DAA adds 60h to the AL and sets the CF.

Source Code. DAA

Object Code. 00100111

DAA ใช้สำหรับปรับค่าของการบวก packed BCD วิธีการปรับค่าของคำสั่ง DAA ทำดังนี้

- ถ้า 4 บิตล่างของเรจิสเตอร์ AL มีค่ามากกว่า 9 หรือ AF = 1 จะบวกค่า 6 กับเรจิสเตอร์ AL และกำหนดให้ AF = 1

- ถ้า 4 บิตบนของเรจิสเตอร์ AL มีค่ามากกว่า 9 หรือ CF = 1 จะบวกค่า 60h กับเรจิสเตอร์ AL และกำหนดให้ CF = 1

ตัวอย่าง

ก. ผลลัพธ์เก็บใน AL พอ

; AL = 0101 1001 = 59 BCD

; BL = 0011 0101 = 35 BCD

ADD AL,BL ; AL =1000 1110 = 8EH incorrect

DAA ; AL = 1001 0100 = 94 BCD

AL 0101 1001 59H

BL 0011 0101 35H

ADD AL,BL

AL 1000 1110 8EH

CF = 0 AF = 0

DAA

AL 1000 1110

0000 0110 6H because AH > 9 add 6 to AL and set AF = 1

AL 1001 0100 94H

ข. ผลลัพธ์เก็บใน AL ไม่พอ (หลังจากทำคำสั่ง DAA ดู CF =1)

; AL = 1000 1000 = 88 BCD

; BL = 0100 1001 = 49 BCD

MOV AX,88H

MOV BL,49H

ADD AL,BL ; AL =1101 0001 , AF = 1

DAA ; add 0110 because AF = 1

; AL = 1101 0111 = D7H

; 1101 > 9 add 0110 0000

; CF = 1 and AL = 0011 0111 = 37

ADC AH,0 ; AX = 0000 0001 0011 0111 = 0137 BCD

INC : Increment by 1

Operation. Increments by 1 a byte, or word in a register or memory, coded, for example, as INC CX.

Source Code. INC {register/memory}

Object Code. (two formats)

Register: |01000reg|

Reg/memory: |1111111w|mod000r/m|

หมายเหตุ คำสั่งนี้ไม่มีผลกับ CF

5.2.2 Subtraction

SUB : Subtract Binary Numbers

Operation. Subtract binary values in a register, memory, or immediate from a register, or subtracts values in a register or immediate from a memory. Values may be byte or word.

Note! มีผลกับค่า flags ดังนี้

- CF มีค่า 0 ถ้าผลลัพธ์ไม่มีการขอยืมค่า

มีค่า 1 ถ้าผลลัพธ์มีการขอยืมค่า

- PF มีค่า 0 ถ้าผลลัพธ์มีจำนวนบิตที่มีค่า 1 เป็นคี่

มีค่า 1 ถ้าผลลัพธ์มีจำนวนบิตที่มีค่า 1 เป็นคู่

- AF มีค่า 0 ถ้าผลการบวกเลขฐานสิบไม่ต้องปรับค่า (พิจารณาเฉพาะการยืมค่าจากบิต 4 ของ AL)

มีค่า 1 ถ้าผลการบวกเลขฐานสิบต้องปรับค่า (พิจารณาเฉพาะการยืมค่าจากบิต 4 ของ AL)

- ZF มีค่า 0 ถ้าผลลัพธ์ไม่ใช่ 0

มีค่า 1 ถ้าผลลัพธ์เป็น 0

- SF มีค่า 0 ถ้าผลลัพธ์มีค่าบวก

มีค่า 1 ถ้าผลลัพธ์มีค่าลบ

- OF มีค่า 1 ถ้าการลบเลขที่มีเครื่องหมายต่างกันให้ผลลัพธ์ที่ใหญ่หรือเล็กกว่าที่จะเก็บได้ เช่น ลบเลขขนาด 8 บิต ได้ผลลัพธ์น้อยกว่า –128 หรือมากกว่า 127 เป็นต้น

Source Code. SUB {register/memory},{register/memory/immediate}

Object Code. (three formats)

Reg/mem with reg: |001010dw|modregr/m|

Immed to accumu’r: |0010110w|---data---|data if w=1|

Immed to reg/mem: |100000sw|mod101r/m|---data---|data if sw=01|

ตัวอย่าง

; AL = 01110011 = signed +115 decimal = unsigned 115 decimal

; BL = 11101110 = signed -18 decimal = unsigned 238 decimal

sub al,bl ; al เก็บผลลัพธ์ = 10000101 , bl unchanged

;CF = 1, AF = 1, ZF = 0, SF = 1, OF = 1, PF = 0

sign bit ; unsigned subtraction invalid signed subtraction invalid

bit 7654 3210

AL 0111 0011 operands have the different sign

BL 1110 1110 for signed result can not fit so OF = 1

AL 1000 0101 # of 1 is odd PF = 0, bit 7 is 1 so SF =1, result ( 0 so ZF = 0

1 1

CF AF

คำสั่ง SUB ก็เหมือนกับคำสั่ง ADD จะลบเลขฐาน 2 ดังกล่าวข้างต้นเสมอ ท่านผู้ซึ่งเป็นคนเขียนโปรแกรมต้องตีความเองว่า ท่านกำลังลบเลขที่มีเครื่องหมายหรือไม่มีเครื่องหมาย ถ้าท่านลบเลขที่มีเครื่องหมาย ท่านจะตรวจสอบว่าผลลัพธ์ overflow ได้โดยตรวจสอบจาก OF = 1 ได้ เช่น ตัวอย่างข้างต้น (+115) - (-18) = +133 ซึ่งมีค่าเกิน +127 ซึ่งถ้าดูจากผลลัพธ์แล้ว 1000 0101 มีค่าเท่ากับ –123 ซึ่งไม่ถูกต้อง แต่ถ้าท่านลบเลขที่ไม่มีเครื่องหมาย ท่านจะตรวจสอบว่าผลลัพธ์ overflow ได้โดยตรวจสอบจาก OF = 1 ไม่ได้ เพราะถ้าดูจากตัวอย่างข้างต้น 115 - 238 = -123 ซึ่งไม่ถูกต้อง (เพราะผลลัพธ์ 1000 0101 = 133) การตรวจสอบว่าการลบเลขที่ไม่มีเครื่องหมายให้ผลลัพธ์ที่ถูกต้องหรือไม่ให้ดูที่ CF = 1 หรือไม่

SBB : Subtract with Borrow

Operation. Typically used in multiword binary subtraction to carry an overflowed 1-bit into the next stage of arithmetic. If the CF flag is set, SBB first subtract 1 from operand 1. SBB always subtracts operand 2 from operand 1, just like SUB.

Source Code. SBB {register/memory},{register/memory/immediate}

Object Code. (three formats)

Reg/mem with reg: |000110dw|modregr/m|

Immed to accumu’r: |0001110w|---data---|data if w=1|

Immed to reg/mem: |100000sw|mod011r/m|---data---|data if sw=01|

หมายเหตุ เหมือน SUB แต่รวม carry flag(CF) ด้วย คือ destination = destination – carry - source

ตัวอย่าง

sub ax,cx

sbb bx,dx

SBB BX,DX SUB AX,CX

BX

CF AX

CX

DX

BX AX

AAS : ASCII Adjust for Subtraction

Operation. Corrects subtraction of two ASCII bytes in the AL. If the rightmost four bits of the AL have a value greater than 9 or if the CF flag is 1, AAS subtracts 6 from the AL, subtracts 1 from the AH, and sets the AF and CF flags. Otherwise, the AF and CF are cleared. AAS always clears the leftmost four bits of the AL.

Source Code. AAS

Object Code. 00111111

ใช้สำหรับการปรับค่าการลบเลข ASCII หรือ Unpacked BCD เหมือนกับที่มีการปรับค่าของคำสั่ง AAA

คำสั่ง AAS จะปรับค่า โดยการพิจารณาค่า 4 บิตล่างของ AL ถ้ามีค่าระหว่าง 0-9 ก็จะทำให้ 4 บิตบนของ AL มีค่าเป็น 0 และกำหนดให้ AF กับ CF มีค่าเป็น 0 แต่ถ้า 4 บิตล่างของ AL มีค่ามากกว่า 9 หรือ AF มีค่า 1 จะมีวิธีการปรับค่า ดังนี้

- ลบ 6 จากเรจิสเตอร์ AL

- ลบ 1 จากเรจิสเตอร์ AH

- AF = 1 และ CF = 1

- 4 บิตบนของเรจิสเตอร์ AL มีค่า 0

ตัวอย่าง

ก.

; AL = 0011 0111 = 37H ASCII 7

; BL = 0011 0100 = 34H ASCII 4

MOV AL,37H

MOV BL,34H

SUB AL,BL ; (7-4)

AAS ; CL = 0000 0011 = unpacked BCD 03

ข.

; AL = 0011 0100 = 34H ASCII 4

; CL = 0011 0111 = 37H ASCII 7

MOV AL,34H

MOV CL,37H

SUB AL,CL ; (4-7) = borrow 1 and result 14 – 7 = 7

; AL = 1111 1101, AF = 1, CF = 1

AAS ; AL = 0000 0111 = unpacked BCD 07

; CF = 1 borrow needed

DAS : Decimal Adjust for Subtraction

Operation. Corrects the result of subtracting two BCD (packed decimal) items in the AL. If the rightmost four bits have a value greater than 9 or the AF flag is 1, DAS subtracts 6 from the AL and sets the AF. If the leftmost four bits have a value greater than 9 or the CF flag is 1, DAS subtracts 60h from the AL and sets the CF.

Source Code. DAS

Object Code. 00101111

ใช้สำหรับการปรับค่าการลบเลข packed BCD เหมือนกับที่มีการปรับค่าของคำสั่ง DAA

คำสั่ง DAS มีวิธีการปรับค่า ดังนี้

- ถ้า 4 บิตล่างของเรจิสเตอร์ AL มีค่ามากกว่า 9 หรือ AF = 1 จะลบค่า 6 จากเรจิสเตอร์ AL และกำหนดให้ AF = 1

- ถ้า 4 บิตบนของเรจิสเตอร์ AL มีค่ามากกว่า 9 หรือ CF = 1 จะลบค่า 60h จากเรจิสเตอร์ AL และกำหนดให้ CF = 1

ตัวอย่าง

ก.

; AL = 1000 0110 = 86 packed BCD

; BH = 0101 0111 = 57 packed BCD

SUB AL,BH ; AL =0010 1111 = 2FH

DAS ; subtract 0000 0110

; because 1111 in low nibbles > 9

; AL = 0010 1001 = 29 packed BCD

ข.

; AL = 0100 0101 = 45 packed BCD

; BH = 0110 0011 = 63 packed BCD

SUB AL,BH ; AL = 1110 0010, CF = 1

DAS ; subtract 0110 0000

; because 1010 in upper nibbles > 9

; AL = 1000 0010 = 82 packed BCD, CF = 1

; CF = 1 means borrow was needed

DEC : Decrement by 1

Operation. Decrements 1 from a byte, or word in a register or memory, coded, for example, as DEC CX.

Source Code. DEC {register/memory}

Object Code. (two formats)

Register: |01001reg|

Reg/memory: |1111111w|mod001r/m|

NEG : Negate

Operation. Reverses a binary value from positive to negative and from negative to positive. NEG provides two’s complement of the specified operand: subtracts the operand from zero and adds 1. Operands may be a byte or word in a register or memory.

Note! มีผลกับค่า flags ดังนี้

- CF มีค่า 0 ถ้าผลลัพธ์เป็นบวก

มีค่า 1 ถ้าผลลัพธ์เป็นลบ

- PF มีค่า 0 ถ้าผลลัพธ์มีจำนวนบิตที่มีค่า 1 เป็นคี่

มีค่า 1 ถ้าผลลัพธ์มีจำนวนบิตที่มีค่า 1 เป็นคู่

- AF มีค่า 0 ถ้าผลการบวกเลขฐานสิบไม่ต้องปรับค่า

มีค่า 1 ถ้าผลการบวกเลขฐานสิบต้องปรับค่า

- ZF มีค่า 0 ถ้าผลลัพธ์ไม่ใช่ 0

มีค่า 1 ถ้าผลลัพธ์เป็น 0

- SF มีค่า 0 ถ้าผลลัพธ์มีค่าบวก

มีค่า 1 ถ้าผลลัพธ์มีค่าลบ

- OF มีค่า 1 ถ้าผลลัพธ์ใหญ่หรือเล็กกว่าที่จะเก็บได้ และมีค่าเป็น 0 ในกรณีอื่น

Source Code. NEG {register/memory}

Object Code. |1111011w|mod011r/m|

CMP : Compare

Operation. Compares the contents of two data fields. CMP internally subtracts operand 2 from operand 1 but does not change the values. Both operands are byte or word. CMP may compare register, memory, or immediate to a register or compare register or immediate to memory.

Source Code. CMP {register/memory},{register/memory/immediate}

Object Code. (three formats)

Reg/mem with reg: |001110dw|modregr/m|

Immed to accum’r: |0011110w|---data---|-data if w=1-|

Immed to reg/mem: |100000sw|mod111r/m|---data---|-data if sw = 00|

คำสั่ง CMP มีการทำงานคล้ายคำสั่ง SUB คือ CMP จะลบ source จาก destination แต่ไม่ได้เก็บค่าผลลัพธ์ ดังนั้นค่าใน source และ destination จึงไม่มีการเปลี่ยนแปลงจากการลบ ทำให้ได้ผลลับ flags ดังนี้

condition OF SF ZF CF

Unsigned Operands

source < destination x x 0 0

source = destination x x 1 0

source > destination x x 0 1

Signed Operands

source < destination 0/1 0 0 x

source = destination 0 0 1 x

source > destination 0/1 1 0 x

Note! x means don’t care 0 is clear 1 is set

5.2.3 Multiplication

MUL : Unsigned Multiplication

Operation. Multiplies an unsigned multiplicand by an unsigned multiplier. MUL treats a leftmost 1-bit as a data bit, not a negative sign. Here are the two operations:

Multiplicand Multiplier

(operand1) (operand 2) Product Example

8-bit AL 8-bit register/memory AX MUL BL

16-bit AX 16-bit register/memory DX:AX MUL BX

Source Code. MUL {register/memory}

Object Code. |1111011w|mod100r/m|

ใช้คูณเลขจำนวนเต็มไม่มีเครื่องหมาย สามารถคูณเลขขนาดไบต์และคำได้ มีรูปแบบการใช้ ดังนี้

MUL multiplier

โดยที่ multiplier เป็นได้ทั้งเรจิสเตอร์หรือหน่วยความจำ

สำหรับการคูณข้อมูลขนาดไบต์จะใช้ AL เป็น multiplicand และ แต่ถ้าเป็นการคูณข้อมูลขนาดคำจะใช้ AX เป็น multiplicand ผลลัพธ์จากการคูณ จะมีขนาดเป็นสองเท่า ถ้าเป็นการคูณข้อมูลขนาดไบต์ ผลลัพธ์จะมีขนาด 16 บิต เก็บอยู่ใน AX (หรือ AH:AL) ถ้า AH มีค่าเป็น 0 แฟลก CF และ OF จะมีค่าเป็น 0 มิฉะนั้นจะมีค่าเป็น 1 แต่ถ้าเป็นการคูณข้อมูลขนาดคำ ผลลัพธ์จะมีขนาด 32 บิต เก็บอยู่ใน DX:AX ถ้า DX มีค่าเป็น 0 แฟลก CF และ OF จะมีค่าเป็น 0 มิฉะนั้นจะมีค่าเป็น 1

การคูณข้อมูลขนาดคำ

AX

BX

CX

DX

AX DX AX

*

SI

DI

BP

SP

word memory

การคูณข้อมูลขนาดไบต์

AH

AL

BH

BL

CH

CL

DH

DL

AL AH AL

*

byte memory

ตัวอย่าง

mov al,5

mov bl,10

mul bl ; 5 * 10 , ax = 50

IMUL : Signed (Integer) Multiplication

Operation. Multiplies a signed multiplicand by a signed multiplier. IMUL treats a leftmost 1-bit as a negative sign. Here are the two operations:

Multiplicand Multiplier

(operand1) (operand 2) Product Example

8-bit AL 8-bit register/memory AX IMUL BL

16-bit AX 16-bit register/memory DX:AX IMUL BX

Source Code. IMUL {register/memory}

Object Code. |1111011w|mod101r/m|

เหมือน MUL แต่เป็นการคูณเลขจำนวนเต็มมีเครื่องหมาย และถ้าผลคูณไม่สามารถเก็บได้พอใน AL (กรณี 8 บิต) หรือ AX (ในกรณี 16 บิต) ค่าใน CF และ OF จะเป็น 1 มิฉะนั้น จะเป็น 0

AAM : ASCII Adjust for Multiplication

Operation. Corrects the product generated by multiplying two unpacked decimal values. AAM divides the AL by 10 and stores the quotient in the AH and the remainder in the AL.

Source Code. AAM

Object Code. |11010100|00001010|

คำสั่ง AAM จะเปลี่ยนค่าของผลลัพธ์ของการคูณเลขขนาดไบต์ เป็นค่า unpacked BCD 2 ค่า เก็บใน AH และ AL โดยที่ตัวตั้งและตัวคูณต้องเป็น unpacked BCD ด้วย

ในการปรับค่าผลลัพธ์ คำสั่ง AAM จะหารเรจิสเตอร์ AL ด้วย 10 และเก็บค่าส่วนใน AH ค่าเศษใน AL เช่น สมมุติว่า AL มีค่า 9 (00001001B) และ BL มีค่า 7 (0000111B) เมื่อใช้คำสั่ง MUL BL ผลลัพธ์ของการคูณ AL กับ BL ได้ผลลัพธ์ 00000000B เก็บใน AH และ 00111111B เก็บใน AL เมื่อใช้คำสั่ง AAM เรจิสเตอร์ AL จะถูกหารด้วย 10 แล้วเก็บส่วน คือ 00000110B ไว้ใน AH และเก็บเศษ คือ 00000011B ไว้ใน AL

ตัวอย่าง

; AL = 00000101 = unpacked BCD 5

; BH = 00001001 = unpacked BCD 9

mul bh ;al * bh result in ax

;ax = 00000000 00101101 = 002dh

aam ;ax = 00000100 00000101

; = unpacked BCD 45

5.2.4 Division

DIV : Unsigned Division

Operation. Divides an unsigned dividend by an unsigned divisor. DIV treats a leftmost 1-bit as a data bit, not a minus sign. Here are the two types of division:

Dividend Divisor

(operand1) (operand 2) Quotient Remainder Example

16-bit AX 8-bit register/memory AL AH DIV BH

32-bit DX:AX 16-bit register/memory AX DX DIV CX

Note! Division by zero causes a zero-divide interrupt.

Source Code. DIV {register/memory}

Object Code. |1111011w|mod110r/m|

กรณีที่ผลหาร (quotient) ไม่สามารถเก็บได้พอใน AL (กรณี 8 บิต) หรือ AX (กรณี 16 บิต) จะเกิด divide by zero interrupt

การหารจะคล้ายกับการคูณ แต่ทำกลับกัน ดังนี้

การหารข้อมูลขนาดคำ

AX

BX

CX

DX

DX AX DX AX

/

เศษ จำนวนเต็ม

SI

DI

BP

SP

word memory

การหารข้อมูลขนาดไบต์

AH

AL

BH

BL

CH

CL

DH

DL

AX AH AL

/

เศษ จำนวนเต็ม

byte memory

ตัวอย่าง

mov ax,13

mov bl,5

div bl ; 13 / 5 , ah = 3, al = 2

ตัวอย่าง

; unsigned integer

; x = a/b

; y = a mod b

dosseg

.model small

.stack 1024

.data

x dw ?

y dw ?

a dw 7

b dw 3

.code

main proc

mov ax,@data

mov ds,ax

mov ax,a

mov dx,0 ; xor dx,dx

div b

mov x,ax ; x = 2

mov y,dx ; y = 1

mov ax,4c00h

int 21h

main endp

end main

IDIV : Signed (Integer) Division

Operation. Divides a signed dividend by a signed divisor. DIV treats a leftmost 1-bit as a negative sign. Here are the two types of division:

Dividend Divisor

(operand1) (operand 2) Quotient Remainder Example

16-bit AX 8-bit register/memory AL AH IDIV BH

32-bit DX:AX 16-bit register/memory AX DX IDIV CX

Note! Division by zero causes a zero-divide interrupt.

Source Code. IDIV {register/memory}

Object Code. |1111011w|mod111r/m|

กรณีที่ผลหาร (quotient) ไม่สามารถเก็บได้พอใน AL (กรณี 8 บิต) หรือ AX (กรณี 16 บิต) จะเกิด divide by zero interrupt

เหมือน DIV แต่เป็นการหารเลขที่มีเครื่องหมาย

ตัวอย่าง

Dividend(AX) Divisor Quotient (AL) Remainder(AH)

7 2 3 1

7 -2 -3 1

-7 2 -3 -1

-7 -2 3 -1

Note! The sign of the remainder is always the same as the dividend.

ตัวอย่าง

; signed integer

; x = a/b

; y = a mod b

dosseg

.model small

.stack 1024

.data

x dw ?

y dw ?

a dw -7

b dw 3

.code

main proc

mov ax,@data

mov ds,ax

mov ax,a

cwd

idiv b

mov x,ax ; x = -2 or 0FFFEh

mov y,dx ; y = -1 or 0FFFFh

mov ax,4c00h

int 21h

main endp

end main

ตัวอย่าง

; signed integer

; x = ((a+b)/d)*5

dosseg

.model small

.stack 1024

.data

x dw ?

a dw 120

b dw -20

d dw 4

.code

main proc

mov ax,@data

mov ds,ax

mov ax,a

add ax,b

cwd

idiv d

mov bx,5

imul bx

mov x,ax ; x = 125 or 7Dh

mov ax,4c00h

int 21h

main endp

end main

AAD : ASCII Adjust for Division

Operation. Corrects for division of ASCII values Use AAD before dividing into an unpacked decimal value in the AX (strip out ASCII 3s). AAD corrects the dividend to a binary value in the AL for a subsequent binary divide. It multiplies the AH by 10, adds the product to the AL, and clears the AH.

Source Code. AAD

Object Code. |11010101|00001010|

คำสั่ง AAD จะปรับค่าของตัวตั้งในการหารให้เป็นเลขฐานสอง ในเรจิสเตอร์ AL ซึ่งทำการโดยการคูณส่วนบนของตัวตั้งหรือค่าในเรจิสเตอร์ AH ด้วย 10 และบวกผลลัพธ์กับส่วนล่างของตัวตั้งหรือค่าในเรจิสเตอร์ AL และจะทำให้ค่าใน AH เป็น 0 คำสั่ง AAD จะต้องถูกเรียกใช้ก่อนการหาร

ตัวอย่าง

; AX = 0000 0011 0000 0111 unpacked BCD for 37 decimal

; CL = 0000 0101 unpacked BCD for 5 decimal

aad ; adjust to binary before division

; ax = 0025h = 37

div cl ; divide ax by cl

; al = quotient = 07 unpacked BCD

; ah = remainder = 02 unpacked BCD

5.2.5 Sign-Extension

CBW : Convert Byte to Word

Operation. Extends a one-byte signed value in the AL to a word by duplicating the sign (bit 7) of the AL through the bits in the AH.

Source Code. CBW

Object Code. 10011000

คำสั่ง CBW เป็นคำสั่งที่ลอกค่าของบิต 7 ในเรจิสเตอร์ AL ไปใส่ในเรจิสเตอร์ AH

7 0 7 0

AH AL

ปกติใช้เพื่อเปลี่ยนข้อมูลที่มีเครื่องหมายขนาดไบต์ให้เป็นขนาดคำ ก่อนการบวกหรือลบ

CWD : Convert Word to Doubleword

Operation. Extends a one-word signed value in the AX to a doubleword by duplicating the sign (bit 15) of the AX through the DX, typically to generate a 32-bit dividend.

Source Code. CWD

Object Code. 10011001

คำสั่ง CWD เป็นคำสั่งที่ลอกค่าของบิต 15 ในเรจิสเตอร์ AX ไปใส่ในเรจิสเตอร์ DX

15 0 15 0

DX AX

ปกติใช้เพื่อเปลี่ยนข้อมูลที่มีเครื่องหมายขนาดคำให้เป็นขนาดสองคำ ก่อนการหาร

สรุป คำสั่งที่เกี่ยวข้องกับการบวกลบคูณหาร

integer

binary decimal

signed unsigned ASCII Unpacked BCD Packed BCD

addition

add des,src เหมือน signed aaa aaa daa

or al,30h

adc des,src เหมือน signed

inc des เหมือน signed

subtraction

sub des,src เหมือน signed aas aas das

or al,30h

sbb des,src เหมือน signed

dec des เหมือน signed

neg des

cmp des,src เหมือน signed

multiplication

imul src mul src aam

division

cbw

cwd

aad

idiv src div src

หมายเหตุ การบวกลบคูณหาร (ASCII, Unpacked BCD) และ Packed BCD

อย่าลืม ว่าทำได้ทีละไบต์ และ destination ต้องเป็น AL เท่านั้น ข้อมูลที่จะต้องนำมากระทำการต้องเก็บเป็นตัวเลขที่ถูกต้อง เช่น ASCII 5 และ Unpacked BCD 5 ต้องเก็บเป็น 35H และ 05H ตามลำดับ เป็นต้น หรือ Packed BCD

5 และ 24 ต้องเก็บเป็น 05H และ 24H เป็นต้น เลขเหล่านี้จะต้องอยู่ในช่วง 0 ถึง 9 จึงจะถูกต้อง

การบวก

1. ASCII หรือ Unpacked BCD

- ใส่ ASCII หรือ Unpacked BCD ใน AL

- ใช้คำสั่ง add (หรือ adc ถ้าต้องการนำ CF มาบวกด้วย) โดยมี AL เป็น destination และ ASCII หรือ Unpacked BCD ที่ต้องการนำมาบวกเป็น source

- ใช้คำสั่ง aaa เพื่อปรับค่าให้ถูกต้อง และจะกำหนดให้ 4 บิตบนของ AL เป็น 0 เสมอ ถ้ามีการทดจะกำหนดให้ AF และ CF มีค่าเป็น 1 และบวก AH ด้วย 1

- คำตอบจะเป็น Unpacked BCD ที่ต้องการ เพราะคำสั่ง aaa จะปรับค่าให้ 4 บิตบนของ AL เป็น 0 เสมอ ถ้าต้องการคำตอบในรูป ASCII ให้ใช้คำสั่ง or al,30h อีกคำสั่งหนึ่ง ถ้าต้องการดูว่ามีการทดหรือไม่ให้ดูที่ CF หรือ AF

ต.ย.

1) กรณีไม่มีการทด เช่น 35h+34h

ASCII binary

mov al,35h AL 35h 0011 0101 AH = ?

mov bh,34h BH 34h 0011 0100

add al,bh AL 69h 0110 1001

AF = 0

aaa AL 09h 0000 1001 AH = ?

2) กรณีมีการทด เช่น 39h+39h

ASCII binary

mov al,39h AL 39h 0011 1001 AH = ?

mov bh,39h BH 39h 0011 1001

add al,bh AL 72h 0111 0010

AF = 1 ; note 0010 + 0110 = 1000

aaa AL 08h 0000 1000 AH = ? + 1 AF =1 CF = 1

2. Packed BCD

- ใส่ Packed BCD ใน AL

- ใช้คำสั่ง add (หรือ adc ถ้าต้องการนำ CF มาบวกด้วย) โดยมี AL เป็น destination และ Packed BCD ที่ต้องการนำมาบวกเป็น source

- ใช้คำสั่ง daa เพื่อปรับค่าให้ถูกต้อง ถ้ามีการทดใน 4 บิตล่าง AF = 1 และถ้ามีการทดใน 4 บิตบน CF = 1

- คำตอบจะเป็น Packed BCD ที่ต้องการ ถ้าจะตรวจสอบว่ามีการทดหรือไม่ให้ดูที่ CF

ต.ย.

1) กรณีไม่มีการทด เช่น 15h+24h

ASCII binary

mov al,15h AL 15h 0001 0101

mov bh,24h BH 24h 0010 0100

add al,bh AL 39h 0011 1001

CF = 0 AF = 0

daa AL 39h 0011 1001

2) กรณีมีการทด เช่น 93h+16h

ASCII binary

mov al,93h AL 93h 1001 0011

mov bh,16h BH 16h 0001 0110

add al,bh AL a9h 1010 1001

CF = 0 AF = 0 ; note 1010 + 0110 = 0000

daa AL 09h 0000 1001 AF =0 CF = 1

การลบ

1. ASCII หรือ Unpacked BCD

- ใส่ ASCII หรือ Unpacked BCD ใน AL

- ใช้คำสั่ง sub (หรือ sbb ถ้าต้องการนำ CF มาลบด้วย) โดยมี AL เป็น destination และ ASCII หรือ Unpacked BCD ที่ต้องการนำมาลบเป็น source

- ใช้คำสั่ง aas เพื่อปรับค่าให้ถูกต้อง และจะกำหนดให้ 4 บิตบนของ AL เป็น 0 เสมอ ถ้ามีการยืมจะกำหนดให้ AF และ CF มีค่าเป็น 1 และลบ AH ด้วย 1

- คำตอบจะเป็น Unpacked BCD ที่ต้องการ เพราะคำสั่ง aas จะปรับค่าให้ 4 บิตบนของ AL เป็น 0 เสมอ ถ้าต้องการคำตอบในรูป ASCII ให้ใช้คำสั่ง or al,30h อีกคำสั่งหนึ่ง ถ้าต้องการดูว่ามีการยืมหรือไม่ให้ดูที่ CF หรือ AF

ต.ย.

1) กรณีไม่มีการยืม เช่น 35h-34h

ASCII binary

mov al,35h AL 35h 0011 0101 AH = ?

mov bh,34h BH 34h 0011 0100

sub al,bh AL 01h 0000 0001

AF = 0

aas AL 01h 0000 0001 AH = ?

2) กรณีมีการทด เช่น 38h-39h

ASCII binary

mov al,38h AL 38h 0011 1000 AH = ?

mov bh,39h BH 39h 0011 1001

sub al,bh AL ffh 1111 1111

AF = 1 ; note 1111 - 0110 = 1001

aas AL 09h 0000 1001 AH = ? - 1 AF =1 CF = 1

2. Packed BCD

- ใส่ Packed BCD ใน AL

- ใส่ Packed BCD ในเรจิสเตอร์หรือหน่วยความจำที่ต้องการนำมาลบ

- ใช้คำสั่ง sub (หรือ sbb ถ้าต้องการนำ CF มาลบด้วย) โดยมี AL เป็น destination และ Packed BCD ที่ต้องการนำมาลบเป็น source

- ใช้คำสั่ง das เพื่อปรับค่าให้ถูกต้อง ถ้ามีการยืมใน 4 บิตล่าง AF = 1 และถ้ามีการยืมใน 4 บิตบน CF = 1

- คำตอบจะเป็น Packed BCD ที่ต้องการ ถ้าจะตรวจสอบว่ามีการยืมหรือไม่ให้ดูที่ CF

ต.ย.

1) กรณีไม่มีการยืม เช่น 25h-14h

ASCII binary

mov al,25h AL 25h 0010 0101

mov bh,14h BH 14h 0001 0100

sub al,bh AL 11h 0001 0001

CF = 0 AF = 0

das AL 11h 0001 0001

2) กรณีมีการยืม เช่น 16h-93h

ASCII binary

mov al,16h AL 16h 0001 0110

mov bh,93h BH 93h 1001 0011

sub al,bh AL a9h 1000 0011

CF = 1 AF = 0 ; note 1000 – 0110 = 0010

das AL 23h 0010 0011 ;AF =0 CF = 1

การคูณ

มีเฉพาะ Unpacked BCD เท่านั้น

1. ใส่ตัวตั้งซึ่งเป็น Unpacked BCD ใน AL

2. ใช้คำสั่ง mul โดยมี Unpacked BCD อีกตัวหนึ่งเป็นตัวคูณ

3. ใช้คำสั่ง aam เพื่อปรับค่าผลลัพธ์ที่เก็บใน AX ให้เป็น Unpacked BCD สองตัวเก็บใน AH และ AL ตามลำดับ

ต.ย. Unpacked Binary

mov al,5 AL 05 0000 0101

mov bl,9 BL 09 0000 1001

mul bl AX 002d 0000 0000 0010 1101

aam AX 0405 0000 0100 0000 0101

หมายเหตุ aam หาร AL ด้วย 10 เก็บผลลัพธ์ใน AH และเศษใน AL

การหาร

มีเฉพาะ Unpacked BCD เท่านั้น

1. ใส่ตัวตั้งซึ่งเป็น Unpacked BCD ใน AX

2. ใช้คำสั่ง aad เพื่อปรับค่าจาก Unpacked BCD เป็น binary คำสั่งนี้จะคูณ AH ด้วย 10 แล้วบวกกับ AL

3. ใช้คำสั่ง div โดยมี Unpacked BCD อีกตัวหนึ่งเป็นตัวหาร จะได้ผลลัพธ์เก็บใน AL และเศษเก็บใน AH

ต.ย. Unpacked Binary

mov ax,0307h AX 03 07 0000 0011 0000 0111

aad AX 0025 0000 0000 0010 0101

mov cl,5 CL 05 0000 0101

div cl AX 0207 0000 0010 0000 0111

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download