Chapter 7Integer Arithmetic |
Modified: |
Most instructions such as Add, Mov, Push operate on bytes, words or double words. Bit manipulation instructions provide operations on individual or groups of bits. Most of these instructions operate on registers or variables. Common use of bit manipulation instructions include code conversions, graphics, and hardware control applications.
Before examining the operations in detail it is useful to recall the standard representation of binary numbers which counts digit positions from the right end of the number to the left. For example, the number 10102 is 0 in position 0, 1 in position 1, 0 in position 2, and 1 in position 3 or 13021100. An 8 bit value is then arranged with bits in the position order of 76543210, a 16 bit with digits in positions 15-0, and 32 bit with digits in positions 31-0. The following illustrates the bit positions of 27 hexadecimal.
Position 7654 3210 27 hex 0010 0111 |
The carry flag can be set to a 1 or cleared to a 0 value using the STC and CLC operations respectively.
| STC | CLC |
| CF = 1 | CF = 0 |
Shift
The following branch is always taken: The following branch is never taken: STC
JC doCLC
JC do
The shift operation adds bits on one end of the operand (register or variable) and throws away bits on the other.
The shifts come in two flavors (logical and arithmetic) and two directions (left and right).
Logical - Shifts 0 into vacated bit.
SHR
SHL
Arithmetic - Right shifts sign bit into vacated bit.
SHL and SAL identical.
SAR
SAL
The carry flag is always affected by the last bit shifted.
| Arithmetic | Logical | ||||||||||||
|
|
1. Question
Mov Cl, 7
Mov Ah, 10000000B
SAR Ah, ClAh ____________
CF ____________Mov Cl, 4
Mov Ah, 00001111B
SHL Ah, ClAh _____________
CF _____________
The rotate operation copies bits from one end of the operand (register or variable) to the other.
The rotates come in two flavors (into and through the carry) and two directions (left and right).
The carry flag is always contains the last bit rotated.
| Into Carry Flag | Through Carry Flag | ||||||||||||
|
|
2. Question
CLC
Mov Cl, 2
Mov Ah, 11011111B
ROL Ah, ClAh ____________
CF ____________STC
Mov Cl, 3
Mov Ah, 00000000B
RCL Ah, ClAh _____________
CF _____________
Example Using Shift and Rotate
Shift
The following example counts the number of 1 bits in the Bh register by shifting and examining each individual bit into the carry flag.
Note that Bh=00000000 at the end and eAx=3.
.code Main Proc Mov Bh, 01001001B ; Bh = 01001001 Mov eAx, 0 ; eAx = 0 .WHILE Bh != 0 ; while(Bh != 0) { Shr Bh, 1 ; Cf = Bh >> 1; .IF CARRY? ; if (Cf == 1) Inc eAx ; eAx++; .ENDIF .ENDW Exit Main Endp End MainRotate
Parity is used for error detection in data transmissions.
Even parity means that the number of 1 bits is even in the data and the parity.
Using even parity, the data 00000001 would have a parity bit of 1.
The parity of Ah is indicated in Al=0 when parity bit is 0, otherwise Al=0ffh.
.code Main Proc Mov Ah, 01001001B ; Ah = 01001001 Mov Al, 0 ; Al = 0 Mov Cl, 8 ; Cl = 8 .REPEAT ; repeat { Ror Ah, 1 ; Cf = Ah rotate 1; .IF CARRY? ; if (Cf == 1) Not Al ; Al = !Al; .ENDIF ; } until( --Cl == 0 ); Dec Cl .UNTIL Cl == 0 Exit Main Endp End Main
Addition and Subtraction
The add and subtract operation can operate on signed or unsigned numbers, either 8 or 16-bit operands. The result is the same size as the operands so it is possible that incorrect results are produced when the result is too large or small. Remember that subtraction is performed by addition of a negative number.
Addition/Subtraction Examples
00000000 Carry into and out of leftmost 8 bits 110 000000012 bit equal, OF=0. +8 bits +110 = +000000012 8 bits 210 0000000102 Valid unsigned, CF=0. CF = 0 ZF = 0 Valid signed OF=0. OF = 0 SF = 0 |
Unsigned 11111111 Signed Carry into and out of leftmost. 8 bits 25510 111111112 -1 bit equal, OF=0 +8 bits +110 = +000000012 = +1 8 bits 010 1000000002 0 Invalid unsigned, CF=1. CF = 1 ZF = 1 Valid signed, OF=0. Mov Ah, 255 OF = 0 SF = 0 Add Ah, 1 Ah = 0 |
Unsigned 11111111 Signed Carry into and out of leftmost 8 bits 110 000000012 110 bit equal, OF=0. +8 bits +25510 = +111111112 = +(-110) 8 bits 010 1000000002 0 Invalid unsigned, CF = 1. CF = 1 ZF = 1 Valid signed, OF = 0. Mov Ah, 1 OF = 0 SF = 0 Add Ah, 255 OR Ah = 0 Add Ah, -1 |
Unsigned 11111111 Signed Carry into and out of leftmost 8 bits 110 000000012 110 bit equal, OF=0. -8 bits -110 = +111111112 -110 8 bits 010 1000000002 0 Valid unsigned, CF=0 since CF = 0 ZF = 1 inverted on subtraction Mov Ah, 1 OF = 0 SF = 0 Valid signed, OF=0. Sub Ah, 1 Ah = 0 |
Unsigned 01111111 Signed Carry into and out of leftmost 8 bits 12710 011111112 12710 bit equal, OF=0. +8 bits +110 = +000000012 +110 8 bits 12810 0100000002 = -128 Valid unsigned 128, CF=0. CF = 0 ZF = 0 Invalid signed -128, OF=1. Mov Ah, 127 OF = 1 SF = 1 Add Ah, 1 |
Unsigned 10000000 Signed Carry in 0, carry out of leftmost 8 bits 12810 100000002 -12810 bit 1, OF=1. +8 bits +12810 = +100000002 +(-128)10 8 bits 010 1000000002 = 0 Invalid unsigned CF=1. CF = 1 ZF = 1 Invalid signed OF=1. Mov Ah, 128 OF = 1 SF = 0 Add Ah, 128 |
Add and Sub Instructions
Negation makes a positive number negative and a negative number positive. For example, -(+1) = -1, -(-1) = +1. Negation only makes sense for signed numbers. If an 8-bit -128 or a 16-bit -32768 is negated the result is invalid, OF=1. An example is:
Mov Ah, -1 Neg Ah ;Ah is now +1Increment and Decrement Instructions
Increment or decrement by one. The overflow, carry, zero, and sign flags have the same meaning as with addition and subtraction. Note that incrementing the 8-bit value 255 (or 16-bit 65535) rolls an unsigned number to 0. However, incrementing a signed number has the sequence of 126, 127, -128, -127, -126. For example:
Unsigned Signed 255 11111111 127 0111111 +1 = 00000001 +1 = +0000001 0 100000000 -128 01000000 CF=1 Invalid unsigned OF = 1 Invalid signed
Mov Ch, 255 Mov Dh, 127 Inc Ch Inc DhMultiply Instruction
9 99 999 11012 *9 *9 *99 *1112 81 891 98901 10110112For 8-bit operands the maximum result is 16-bits in Ax register. Al is always one of the operands in 8-bit multiplication. If the result in Ax requires both the AH and Al registers, OF=1. An example is:
For 16-bit operands the maximum result is 32-bits in DX (high 16-bits) and Ax (low 16-bits). If the result in Dx:Ax requires both the Dx and Ax registers, OF=1. Ax is always one of the operands. An example is:Mov Al, 2 Mov Al, 128 Al Al Mov Bl, 4 Mov Bl, 4 *8-bit operand *4 Mul Bl Mul Bl Ax Ax Ah Al OF Ah Al OF 00 08 0 02 00 1
Mov Ax, 2 Mov Ax, 0FFFFh Ax Ax Mov Bx, 4 Mov Bx, 4 *16-bit operand *4 Mul Bx Mul Bx Dx:Ax Dx:Ax Dx Ax OF Dx Ax OF 0000 0008 0 0003 FFFC 1
For 32-bit operands the maximum result is 64-bits in eDX (high 32-bits) and eAx (low 32-bits). If the result in eDx:eAx requires both the eDx and eAx registers, OF=1. eAx is always one of the operands. An example is:
Mov eAx, 2 Mov eAx, 0FFFFFFFFh eAx eAx Mov eBx, 4 Mov eBx, 4 *32-bit operand *4 Mul eBx Mul eBx eDx:eAx eDx:eAx eDx eAx OF eDx eAx OF 00000000 00000008 0 00000003 FFFFFFFC 1
Mov Al, 2 Mov Al, 11111111B Al Al Mov Bl, 4 Mov Bl, 4 *8-bit operand *4 IMul Bl IMul Bl Ax Ax Ah Al OF Ah Al OF 00 08 0 11111111 11111100 0
Mov Ax, 2 Mov Ax, -2 Ax Ax Mov Bx, -4 Mov Bx, -4 *16-bit operand *-4 IMul Bx IMul Bx Dx:Ax Dx:Ax Dx Ax OF Dx Ax OF FFFF FFF8 0 0000 0008 0
Mov eAx, 2 Mov eAx, -2 eAx eAx Mov eBx, -4 Mov eBx, -4 *32-bit operand *-4 IMul eBx IMul eBx eDx:eAx eAx eDx eAx OF eDx eAx OF FFFFFFFF FFFFFFF8 0 00000000 00000008 0
3. Question
Division Instruction
Mov Al, 10000000B
Mov Ah, 0
Mov Bh, 2
Mul BhAl ____________
Ah ____________
Bh ____________
OF ____________Mov Al, 10000000B
Mov Ah, 0
Mov Bh, 2
IMul BhAl ____________
Ah ____________
Bh ____________
OF ____________
Mov Dx, 0 Mov Ax, 23 Mov Ax, 23 Mov Ch, 5 Mov Cx, 5 Div Ch Div Cx Ah Al Dx Ax 03 04 0003 0004 Mov Dx, -1 Mov Ax, -23 Mov Ax, -23 Mov Ch, 5 Mov Cx, -5 Idiv Ch Idiv Cx Ah=-3 Al=-4 Dx=-3 Ax=4 FB FC FFFB 0004 |
+ - - + +/+ +/- -/+ -/- + - + - +4 -4 -4 +4 +5/+23 +5/-23 -5/+23 -5/-23 +3 -3 +3 -3 |
Because division always uses Ax (16-bit) or Dx:Ax (32-bit) in the dividend, it is often necessary to convert 8-bit Al to 16-bit Ax (or 16-bit Ax to 32-bit Dx:Ax). Consider the following attempt to divide 7/5 when Ah has a bogus value:
Al 8-bit quotient 8-bit divisor/ Ah:Al 16-bit dividend Ah 8-bit remainder
Mov Al, 7 001101012 = 52 Wrong! Mov Ah, 1 5=000001012/ 00000001 000001112 = 263 Mov Dh, 5 000000112 = 3 Div DhObviously 52 is wrong! The problem is that Ah=1 was part of the 16-bit dividend in Ax. Ah should have been 0 for unsigned division. A similar problem can occur with signed division, suppose that we attempt -7/5 by:Mov Al, -7 011001012 = 10110 Wrong! Mov Ah, 1 5=000001012/ 00000001 111110012 = 507 Mov Dh, 5 000000102 = 2 Idiv DhThe 10110 answer is even the wrong sign! What happened? The problem is that the sign of 8-bit Al needed to be extended into Ah to correctly convert an 8-bit negative into a 16-bit negative. To see that an 8-bit signed number can be converted to a 16-bit signed number consider adding more zeros to the left of any positive number, it is still the same positive number (e.g. 7=07=007=0007,...). The same is true for negative numbers in two's complement representation. A 4-bit -1=11112, as 5-bits -1=111112, as 10-bits -1=11111111112, etc. Converting a signed 8-bit number to a signed 16-bit number only requires extending the sign of the 8-bit number into all bits of the 16-bit number. For example, the following produces the
correct results for -7/5.
Mov Al, -7 Al=111110012 Mov Ah, 1 Ah=000000012 Mov Dh, 5 Cbw Ah=111111112 Idiv Dh |
Al 111111112 = -1 Correct! 5=000001012/ 11111111 111110012 = -7 Ah 111111102 = -2 |
Mov Al, 255 Mov Ax, 65535 Mov Dh, 10 Mov Bx, 10000 Mov Ah, 0 Mov Dx, 0 Div Dh Div Bx
8-bit 16-bit 32-bit Mov Al, -17 Mov Ax, -17 Mov eAx, -17 Mov Bh, 5 Mov Bx, 5 Mov eBx, 5 Cbw Cwd Cdq Idiv Bh Idiv Bx iDiv eBx
Al = -3 Ax = -3 eAx = -3 Ah = -2 Dx = -2 eDx = -2
4. Question
Mov Al, 10000000B
Mov Ah, 0
Mov Bh, 2
Div BhAl ____________
Ah ____________
Bh ____________Mov Al, 10000000B
Cbw
Mov Bh, 2
IDiv BhAl ____________
Ah ____________
Bh ____________
Divide Errors
Division by zero results in an exception being thrown, terminating execution.
mov al, -17 mov bh,0 cbw idiv bh
Division can produce a quotient or remainder that is larger than the registers, resulting in an exception being thrown, terminating execution.
mov ax, 256 mov bh,1 div bh
al cannot hold quotient 256 = 1000000002
7.4.6 Implementing Arithmetic Expressions
Algebraic expressions have an implied precedence of:
()
- unary
*, /
+, - binaryTranslations from algebraic representation to assembler must maintain that precedence.
Example
6 + 3 - 4 * 7 / 2 = -5
mov al, 7 mov bh, 4 imul bh ; 4*7 mov bh, 2 ; 4 * 7 / 2 idiv bh mov bx, 6 ; 6 + 3 add bx, 3 sub bx, ax ; 6 + 3 - 4 * 7 / 2