Chapter 4

Data Transfers, Addressing
and Arithmetic

Modified

4.1    Data Transfer Instructions

Recall memory hierarchically organized.

Must transfer values between CPU registers and memory.

 

Review of CPU registers

General 8, 16 and 32 bit register

Pointer and index registers are 32 bit

32 bits addresses 4 Gb

4.1.2    Operand Types

Defined by number of bytes.

 

4.1.3    Direct Memory Operands

MOV instruction transfers values to/between registers and/or memory.

Example

mov  ax, 1234h

Transfer 1234h to AX register.

Example

mov  ax, 1234h

mov  bx, ax

Transfer 1234h to AX register.

Transfer 1234h to BX register.

Example

mov  ax, X   

X at address 00000000 with hexadecimal value 000F.

Transfer 000F from address 00000000 to AX register.

00000000              .data
00000000 000F             X WORD 15
00000002 0000             Y WORD ?

00000000              .code
00000000              main PROC
00000000 66| A1            mov ax, X
00000000 R
00000006 66| A3            mov Y, ax
00000002 R
                                      exit

00000013              main ENDP
                             END main

Example

mov  Y, ax   

Y at address 00000002.

Transfer value from AX register to address 00000002.

 

4.1.8    Direct-Offset Operands

Arrays start at offset 0.

Other elements stored sequentially in memory at increasing offsets.

Example

A2E is an array definition of 5 bytes stored sequentially as:

0x00405004 41 42 43 44 45 ABCDE

A2E starts at address 0x00405004

A2E array offsets
0 1 2 3 4
'A' 'B' 'C' 'D' 'E'
41 42 43 44 45

mov  al, [A2E+2]

transfers 'C' to AL register.

                  .data  
   Address                                      
   00405004        A2E    BYTE      'ABCDE'
   00405009        Z        WORD    8F28h, 9A53h, 7812h

Example

Z is an array definition of 3 words stored sequentially as:

0x00405008 45 28 8F 53 9A 12 78

Z array in Memory
Index 0 1 2
Offset 0 1 2 3 4 5
Value 28 8F 53 9A 12 78

mov  ax, [Z+4]

transfers 7812 to AX register.

mov  ax, Z[4]

transfers 7812 to AX register.

 

4.2    Addition and Subtraction

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.

 

8-bit 2's Complement Example
                                          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
Range of 32 bit two's complement  -232-1 to 232-1-1 or -2147483648 to 2147483647

 

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

 

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 
                                                 inverted on subtraction
                     CF = 0    ZF = 1            
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 not equal, OF=1. 
+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   

Question - What is CF, OF, ZF and SF?

1.
 
mov al, 01000000b
add al, 01000000b
2. mov al, 01000000b            Remember the CF is inverted in subtraction.
sub al, 01000000b

 

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    		Ah = 11111111
        Neg    Ah                     Ah = 00000001

 

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.

Example

4.2.7    Example Program

TITLE  Addition and Subtraction        (AddSub3.asm)
 
; Chapter 4 example. Demonstration of ADD, SUB,
; INC, DEC, and NEG instructions, and how
; they affect the CPU status flags.
; Last update: 06/01/2006
 
INCLUDE Irvine32.inc
 
.data
Rval   SDWORD ?
Xval   SDWORD 26
Yval   SDWORD 30
Zval   SDWORD 40
 
.code
main PROC
      ; INC and DEC
            mov      ax,1000h
            inc        ax                     ; 1001h
            dec       ax                     ; 1000h
 
      ; Expression: Rval = -Xval + (Yval - Zval)
            mov      eax,Xval
            neg       eax                   ; -26
            mov      ebx,Yval
            sub       ebx,Zval           ; -10
            add       eax,ebx
            mov      Rval,eax           ; -36
 
      ; Zero flag example:
            mov      cx,1
            sub       cx,1                  ; ZF = 1
            mov      ax,0FFFFh
            inc        ax                     ; ZF = 1
 
     ; Sign flag example:
            mov      cx,0
            sub        cx,1                  ; SF = 1
            mov      ax,7FFFh
            add       ax,2                  ; SF = 1
 
     ; Carry flag example:
            mov      al,0FFh
            add       al,1                   ; CF = 1,  AL = 00
 
     ; Overflow flag example:
            mov      al,+127
            add       al,1                   ; OF = 1
            mov      al,-128
            sub       al,1                   ; OF = 1
 
            exit
main ENDP

END main

 

4.3    Data Related Operators and Directives

4.3.1    OFFSET operator

Returns the OFFSET (the address in protected mode) of a data label.

 

                  .data  
   Address                                      
   00405000        X        DWORD    12345678h 
   00405004        Y        BYTE         'ABCDE'
   00405009        Z        WORD       8F28h, 9A53h, 0017h

Example

Above 15 bytes stored sequentially as:

X    0x00405000 78 56 34 12

Y    0x00405004 41 42 43 44 45

Z    0x00405009 28 8F 53 9A 17 00

mov  eAx, OFFSET Y

moves 00405004 to eAx register.

mov  eAx, OFFSET Z

moves 00405009 to eAx register.

mov  eAx, OFFSET Z[4]

moves 0040500D to eAx register.

  X       Y         Z          
00405000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E
  78 56 34 12 41 42 43 44 45 28 8F 53 9A 17 00

3. Question - What is esi?

mov    esi, OFFSET X

mov    esi, OFFSET Y[3]

 

4.4    Indirect Addressing

Indirect addressing used in arrays and accessing parameters in procedures.

 

4.4.1    Indirect Operands

                  .data  
   Address                                      
   00405000        X        DWORD    12345678h 
   00405004        Y        BYTE         'ABCDE'
   00405009        Z        WORD       8F28h, 9A53h, 0017h
                   .code
                        mov     esi, OFFSET Y       ; esi = 00405004
                        mov     al,  [esi]               ; al = 'A'
                        mov	    ah, [esi+1]          ; ah = 'B'
                        add      esi, 2                   ; esi = 00405006
                        mov     cl,   [esi]              ; cl = 'C'
  X       Y         Z          
00405000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E
  78 56 34 12 41 42 43 44 45 28 8F 53 9A 17 00

4. Question - What is ax?

mov    esi, OFFSET Z

mov    ax, [esi]

mov    esi, OFFSET Y+2

mov    al, [esi]

 

4.4.2    Arrays

                  .data  
   Address                                      
   00405000        X        DWORD    12345678h 
   00405004        Y        BYTE         'ABCDE'
   00405009        Z        WORD       8F28h, 9A53h, 0017h
                   .code
                        mov     esi, OFFSET Z       ; esi = 00405009
                        mov     ax,  [esi]              ; ax = 8F28h
                        mov	    bx, [esi+2]          ; bx = 9A53h
  X       Y         Z          
00405000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E
  78 56 34 12 41 42 43 44 45 28 8F 53 9A 17 00

5. Question - What is ax?

mov    esi, OFFSET Z

mov    ax, [esi+4]

mov    esi, OFFSET Y

mov    ax, [esi+2]

 

4.4.1    Indexed Operands

                  .data  
   Address                                      
   00405000        X        DWORD    12345678h 
   00405004        Y        BYTE         'ABCDE'
   00405009        Z        WORD       8F28h, 9A53h, 0017h
                   .code
                        mov     esi, 0                   ; esi = 00000000
                        mov     al,  Y[esi]             ; al = 'A'
                        mov	    ah, Y[esi+1]        ; ah = 'B'
  X       Y         Z          
00405000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E
  78 56 34 12 41 42 43 44 45 28 8F 53 9A 17 00

6. Question - What is ax?

mov    esi, 0

mov    ax, Z[esi+2]

mov    esi, 1

mov    ax, Y[esi+2]

 

Scale Factors

Example

Z values occupy 2 locations of memory.

esi must be incremented by 2 to index the next element.

Or esi increment by 1 and scale by 2, usually clearer code to write and read.

                  .data  
   Address                                      
   00405000        X        DWORD    12345678h 
   00405004        Y        BYTE         'ABCDE'
   00405009        Z        WORD       8F28h, 9A53h, 0017h
                   .code
                        mov     esi, 0                   ; esi = 00000000
                        mov     ax,  Z[esi]            ; ax = 8F28h
                        inc        esi                       ; esi = 00000001
                        mov	    bx, Z[esi*2]        ; bx = 9A53h
  X       Y         Z          
00405000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E
  78 56 34 12 41 42 43 44 45 28 8F 53 9A 17 00

7. Question - What is ax?

mov    esi, 2

mov    ax, Z[esi*2]

 

4.4.4    Pointers

Variable that holds the address of another variable.

NEAR pointers are 32-bit for protected mode.

Example

P holds the address (OFFSET) of Z, 00405009.

                  .data  
   Address                                      
   00405000        X        DWORD    12345678h 
   00405004        Y        BYTE         'ABCDE'
   00405009        Z        WORD       8F28h, 9A53h, 0017h
   0040500F     P        DWORD     Z
                   .code
                        mov     esi, P                   ; esi = 00405009
                        mov     ax,  [esi]              ; ax = 8F28h
  X       Y         Z           P      
00405000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12
  78 56 34 12 41 42 43 44 45 28 8F 53 9A 17 00 09 50 40 00

8. Question - What is ax and bl?

mov    esi, P

mov    ax, [esi+2]

mov     bl, [esi-2]

 

4.5    JMP and LOOP Instructions

4.5.1    JMP

Fetch/execute cycle increments the program counter to fetch the next sequential instruction in memory for execution.

JMP instructions unconditionally transfer program execution to a non-sequential location in memory.

The example below lists the addresses of the program instructions.

JMP     forward

transfers execution by changing the next instruction to fetch from address 00000004 to address 00000008.

00000000 B0 FF              mov    al, -1
00000002 EB 04             JMP    forward
00000004 04 01              add     al, 1
00000006 FE C0              inc      al
00000008         forward:
00000008                        add    ah, 5

When executing JMP forward, the instruction pointer (EIP) is at address 00000004.

To change EIP to address 00000008, CPU adds the distance to the label:

  EIP        00000004
04      + 00000004
  EIP        00000008

 

The example below lists the addresses of the program instructions.

JMP     backward

transfers execution by changing the next instruction to fetch from address 00000006 to address 00000002.

00000000 B0 FF              mov    al, -1
00000002             backward:
00000002 04 01              add     al, 1
00000004 EB FC              JMP    backward
00000006 FE C0              inc      al

When executing JMP backward, the instruction pointer (EIP) is at address 00000006.

To change EIP to address 00000002, the CPU adds the distance to the label, negative because backward JMP:

  EIP        00000006
FC      + FFFFFFFC
  EIP        00000002

 

 

4.5.2    LOOP instruction

Counting repetition, executing a set of statements a fixed number of times, is common in programming.

The LOOP operation:

decrements ecx

if ecx != 0, execution continues at the label.

Example

Output: +5 +4 +3 +2 +1

00000000 B9 00000005                         mov      ecx, 5
00000005                              @do:
00000005 8B C1                                    mov      eax, ecx
00000007 E8 00000000 E                       call       WriteInt
0000000C E2 F7                     @while:   loop      @do    
ecx = 5;
do { 
      System.out.print( ecx );

      ecx--;
 }   while( ecx != 0); 

Example - Indexed operands

Sum 32-bit integers and print intermediate sum.

Output: +9 +15 +18 +23 +33

.data
    array dword 10, 5, 3, 6, 9

.code
   main     PROC
               mov        ecx, 5
               mov        eax, 0
   @do:
               add         eax, array[ecx*4-4]

               call         WriteInt
  @while: loop       @do
int array[] = { 10, 5, 3, 6, 9};

ecx = 5;
eax = 0;

do { 
      eax = array[ecx - 1] + eax;

      System.out.print( eax );

      ecx--;
 }   while( ecx != 0); 
0 4 8 12 16
0 1 2 3 4
10 5 3 6 9

 

Example - Indexed operands

Sum 32-bit integers and print intermediate sum.

Output: +10 +15 +18 +24 +33

.data
    array dword 10, 5, 3, 6, 9

.code
   main     PROC
               mov        ecx, 5
               mov        esi,  0
               mov        eax, 0
   @do:
               add         eax, array[esi]
               call         WriteInt
               add         esi, 4
  @while: loop @do
int array[] = { 10, 5, 3, 6, 9};

ecx = 5;
eax = 0;
esi = 0;

do { 
      eax = array[ esi ] + eax;

      System.out.print( eax );

      esi++;

      ecx--;
 }   while( ecx != 0); 
0 4 8 12 16
0 1 2 3 4
10 5 3 6 9

Example - Copy 32-bit values from one memory area to another

.data
    source dword 10, 5, 3, 6, 9
    dest    dword 5 dup(?)
.code
main      PROC
              mov     ecx, 5
              mov     esi, OFFSET source
              mov     edi, OFFSET dest
@do:
              mov     eax, [esi]
              mov     [edi], eax
              call      WriteInt
              add      esi, 4
              add      edi, 4
@while: loop     @do
Memory at start of execution

0x00405000  0a 00 00 00 05 00 00 00 03 00 00 00 06 00
0x0040500E  00 00 09 00 00 00 00 00 00 00 00 00 00 00
0x0040501C  00 00 00 00 00 00 00 00 00 00 00 00 00 00
 

Memory at end of execution

0x00405000  0a 00 00 00 05 00 00 00 03 00 00 00 06 00
0x0040500E  00 00 09 00 00 00 0a 00 00 00 05 00 00 00
0x0040501C  03 00 00 00 06 00 00 00 09 00 00 00 00 00