Chapter 3

CPU Flags

Flags are 1-bit values holding Boolean (logical) values after operations such as Add, Sub, etc. The CPU has a register with flags that indicate the following (other flags will be examined later):

Unsigned Binary Representation

    5710 = 001110012            110 = 000000012      12810 = 100000002       
     410 = 000001002          12710 = 011111112      25510 = 111111112

Two's Complement Representation

Negative numbers only, convert from positive to negative by forming one's complement and adding 1. The following uses 8-bit values.
                   Invert         +1
             Binary      1's Comp    2's Comp
    -5710 = -001110012  = 11000110  = 11000111 =   -5710          
    -410 =  -000001002  = 11111011  = 11111100 =    -410
    -110 =  -000000012  = 11111110  = 11111111 =    -110
  -12710 =  -011111112  = 10000000  = 10000001 =  -12710
  -12810 =  -100000002 -> 01111111 -> 10000000 =  -12810
  -12910 =  -100000012 -> 01111110 -> 10000000 != -12910     
  -25510 =  -111111112 -> 00000000 -> 00000001 != -25510

 

      Range of 8 bit two's complement   -28-1 to 28-1-1 or -128 to 127
      Range of 16 bit two's complement   -216-1 to 216-1-1 or -32768 to 32767

 

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

 

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

     

                                                      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) or 32 to 64-bit (Cdq)

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

 

Input and Output Instructions

The author has supplied a library of functions for input and output of signed and unsigned 32-bit numbers. The functions are described below and a simple programming example to input two signed numbers, add and output their sum is given.(Chapter 5.3 in Irvine)

 

      

 

  • ReadInt - Inputs a 32-bit signed number from the keyboard and stores into eAx.

 

Call    ReadInt          ; cin >> X
Mov   X, eAx

 

  • ReadDec- Inputs a 32-bit unsigned number from the keyboard and stores into eAx.

 

Call    ReadDec         ; cin >> X
Mov   X, Ax

 

  • WriteInt - Outputs a 32-bit signed number from eAx to the screen. Bh=0 to output with no spaces.

 

Mov   eAx, X             ; cout << X
Mov   Bh, 0
Call    WriteInt

 

  • WriteDec - Outputs a 32-bit unsigned number from eAx to the screen. Bh=0 to output with no spaces.

     

    Mov   eAx, X             ; cout << X
    Mov   Bh, 0
    Call    WriteDec

  • WriteString - Outputs a null-terminated string starting at eDX to the screen.

 

; cout << Message
mov     eDX, offset Message
Call    WriteString

 

  • NewLine - Output a new line to the screen.

 

 

Call    NewLine       ; cout << "\n";

 

 
         

 

 


Document last modified: