Chapter 7

Integer Arithmetic

Modified
Overview

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
Carry Flag Operations

The carry flag can be set to a 1 or cleared to a 0 value using the STC and CLC operations respectively.
 

Carry Flag Operations
STC CLC
CF = 1 CF = 0
 
The following branch is always taken:    The following branch is never taken:
STC
JC    do
CLC
JC    do
Shift

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.

Shift
Arithmetic Logical
Left SAL Right SAR
Mov Cl, 3
Mov Ah, 11111111B    
SAL Ah, Cl
Ah = 11111000
CF = 1
Mov Cl, 3
Mov Ah, 10000000B    
SAR Ah, Cl
Ah = 11110000
CF = 0
Left SHL Right SHR
Mov Cl, 3
Mov Ah, 11111111B     
SHL Ah, Cl
Ah = 11111000
CF = 1
Mov Cl, 3
Mov Ah, 11111111B     
SHR Ah, Cl
Ah = 00011111
CF = 1
 

1.    Question

Mov Cl, 7
Mov Ah, 10000000B    
SAR Ah, Cl

Ah ____________
CF ____________

Mov Cl, 4
Mov Ah, 00001111B     
SHL Ah, Cl

Ah _____________
CF _____________

Rotate

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.

Rotate
Into Carry Flag Through Carry Flag
Left ROL Right ROR
STC
Mov Cl, 3
Mov Ah, 11011111B       
ROL Ah, Cl
Ah = 11111110
CF = 0
STC
Mov Cl, 3
Mov Ah, 11111011B       
ROR Ah, Cl
Ah = 01111111
CF = 0
Left RCL Right RCR
CLC
Mov Cl, 3
Mov Ah, 11111111B       
RCL Ah, Cl
Ah = 11111011
CF = 1
CLC
Mov Cl, 3
Mov Ah, 11111011B      
RCR Ah, Cl
Ah = 11011111
CF = 0
 

2.    Question

CLC
Mov Cl, 2
Mov Ah, 11011111B       
ROL Ah, Cl

Ah ____________
CF ____________

STC
Mov Cl, 3
Mov Ah, 00000000B       
RCL Ah, Cl

Ah _____________
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      Main

Rotate

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 Instruction

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 +1
Increment 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:

Multiply Instruction

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    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    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

Mov    Al, 10000000B
Mov    Ah, 0
Mov    Bh, 2
Mul     Bh 

Al  ____________
Ah ____________
Bh ____________
OF ____________

Mov    Al, 10000000B
Mov    Ah, 0
Mov    Bh, 2
IMul    Bh 

Al  ____________
Ah ____________
Bh ____________
OF ____________

Division Instruction
     
                   Al 8-bit quotient                      Ax 16-bit quotient    
    8-bit divisor/ Ax 16-bit dividend     16-bit divisor/ Dx:Ax 32-bit dividend
                   Ah 8-bit remainder                     Dx 16-bit remainder
                      eAx 32-bit quotient        
    32-bit divisor/ eDx:eAx 64-bit dividend     
                   eDx 32-bit remainder                 
                                                      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
Converting 8 to 16 bit (Cbw) or 16 to 32-bit (Cwd)

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    Dh
Obviously 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   Dh

The 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

 

4.    Question

Mov    Al, 10000000B
Mov    Ah, 0
Mov    Bh, 2
Div     Bh 

Al  ____________
Ah ____________
Bh ____________

Mov    Al, 10000000B
Cbw
Mov    Bh, 2
IDiv    Bh 

Al  ____________
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
*, /
+, - binary

Translations 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