Arithmetic and Logic Instructions Outline • • • • • Declarations Moving data The Flags register Logic instructions Addition & subtraction Declarations section .text ; Normally we put data in .data! myvar1: myvar2: myvar3: myvar4: cs261msg: _start: dw 1234h ; ; dw 1234 ; ; resw ; ; DW 0ABCDh ; ; ; DB “CS 261 is ; ; ; define word variable value=1234h define word variable value=1234d=4D2h define word variable value not specified define word variable value = ABCDh note the leading zero great!” define strings as series of bytes this is not one byte but 16! denotes execution starting label It’s all bytes stored in memory (in this case, in the code segment) 1F 1D 1B 19 17 15 13 11 F D B 9 7 5 3 1 ?? ?? ?? ?? 21 = ‘!’ 61 = ‘a’ 72 = ‘r’ ‘’ 69 = ‘i‘ 31 = ‘1’ 32 = ‘2’ 53 = ‘S’ AB 00 04 12 ?? ?? ?? ?? 74 = ‘t’ 65 = ‘e’ 67 = ‘g’ 73 = ‘s’ 20 = ‘ ’ 39 = ‘9‘ 20 = ‘ ’ 43 = ‘C’ CD 00 D2 34 1E 1C 1A 18 CS:_start 16 14 12 10 E C A 8 cs261msg 6 myvar4 4 myvar3 2 myvar2 0 myvar1 CS – Code segment begins Moving data mov ax, cs mov ds, ax ; make data seg same as code seg ; we would only do this if we want ; get at data in the .text (code) seg mov ax, [myvar2] ; ; ; ; ; mov si, myvar2 mov ax, [si] move value of myvar2 to ax same as mov ax, [2] ax now contains 04D2h si now points to myvar2 it contains 0002h ; move value pointed to by si to ax ; ax again contains 04D2h ; this was an indirect reference Moving Data mov bx, cs261msg ; bx now points to the beginning of ; out “CS 261 is great!” string. ; bx points to the ‘C’ character dec byte [bx + 1] ; new instruction! arg = arg – 1 ; Just changed the S in “CS” to an R mov si, 1 ; now lets use SI as an index inc byte [cs261msg + si] ; new instruction! arg = arg + 1 ; evaluates to inc [8 + 1] = inc [9] ; R becomes an S again! Moving Data ; Memory can be indexed using four registers only!!! ; SI -> offsets from DS ; DI -> offsets from DS ; BX -> offsets from DS ; BP -> offsets from SS mov mov mov mov mov ax, al, ah, cx, ax, [bx] [bx] [si] [di] [bp] ; ; ; ; ; ax al ah cx ax = = = = = word in byte in byte in word in [SS:BP] memory pointed to memory pointed to memory pointed to memory pointed to Stack Operation! by by by by ; In addition, BX + SI, BX + DI, BP + SI, and BP + DI are allowed mov ax, [bx + si] ; ax = [ds:bx+si] mov ch, [bp + di] ; ch = [ss:bp+di] bx bx si di Moving Data ; Furthermore, a fixed 8- or 16-bit displacement can be added mov mov mov mov ax, ah, ax, ax, [23h] ; [bx + 5] ; [bx + si + 107] ; [bp + di + 42] ; ax ah ax ax = = = = word byte word word at at at at [DS:23h] [DS:bx+5] [DS:bx+si+107] [SS:bp+di+42] ; Remember that memory to memory moves are illegal! mov [bx], [si] ; BAD BAD BAD mov [di], [si] ; BAD BAD BAD ; Special case with stack operations pop word [myvar] ; moves data from top of stack to ; memory variable myvar Flags register • The flags register is a collection of bits that determines the state of the processor after an arithmetic or logic operation • Flag bits change after arithmetic and logic instructions (e.g. carry, overflow, zero, sign, parity) • 9 out of the 16 bits of the FLAGS register have meaning in the 8086, 11 out of the 32 bits in the EFLAGS register of the 80386, and 12 out of the 32 bits in the EFLAGS register of the 80486 and higher Flags register AC (Alignment check) (VM) Virtual mode (RF) Resume (NT) Nested task (IOPL) Input/output privilege level (O) Overflow (D) Direction (I) Interrupt (T) Trace (S) Sign (Z) Zero (A) Auxiliary Carry (P) Parity (C) Carry 8086, 8088, 80186 80286 80386, 80486DX 80486SX Important Flags Z – set when the result of the last operation was zero C – Set when there was a carry (or borrow) beyond the most significant bit in the last operation (unsigned overflow) O – Set when the last operation overflowed, when interpreting the operands as signed P – Indicates the parity of the result of the last operation S – The sign bit (MSB) of the result of the last operation D – direction flag, controls the direction of a string stored in memory (more later), changed by cld and std instructions Logic instructions • NOT, AND, OR, XOR NOT A AND A, B OR A, B XOR A, B ; ; ; ; A A A A = = = = ~A A & B A | B A ^ B • NOT does not modify any flags • The other instructions affect – – – – – C (carry flag, they all clear it) O (overflow flag, they all clear it) Z (zero flag, they set it if result is 0) S (sign flag, takes the high order bit of the result) P (parity, number of 1’s in the result) Examples of logic instructions AL 1100 1010 NOT AL AL 0011 0101 AL 0011 0101 BL 0110 1101 AND AL, BL AL 0010 0101 AL 0011 0101 BL 0000 1111 AND AL, BL AL 0000 0101 AL BL 0011 0101 0110 1101 OR AL, BL AL 0111 1101 AL BL 0011 0101 0000 1111 OR AL, BL AL 0011 1111 AL 0011 0101 BL 0110 1101 XOR AL, BL AL 0101 1000 Practical uses of AND/OR instructions • Apply a bit mask to data – Masks are used to force individual bits to specific values – Isolate individual bits or bit fields for examination • Example – In x86 operating systems virtual memory is organized in pages, i.e. chunks of 4096 (1000h) consecutive bytes, aligned with an address which is an integer multiple of the page size – Find the beginning of the page that contains address B9A2C07Eh (clear the least significant 12 bits) – Mask = page_size = FFFFF000h – ANDing B9A2C07E with mask yields B9A2C000 The TEST instruction • TEST is a non-destructive version of AND – – – – – Logically ANDs two operands as AND would Modifies FLAG bits like AND Does not modify the contents of the destination TEST AL,1 sets flags like AND AL,1 but does not modify AL Useful prior to jump instructions Shift left • Syntax • • • • SHL reg, count (immediate) SHL reg, CL (count in register) Moves the left operand a bit position to the left as many times as specified by count or CL The empty positions are filled with 0’s The higher order bit is stored in the C flag The most efficient way to multiply by 2! C SHL Register 0 Example ; Pack the lower nibbles from AH and AL into a single byte in AL ; for example AH = 0110 1101 and AL = 1010 0111 and al, 0Fh shl ah, 4 or al, ah ; Mission accomplished ; ; ; ; ; ; clears upper nibble in AL AL = 0000 0111 Moves lower nibble in AH up AH = 1101 0000 combines nibbles AL = 1101 0111 Shift right • Syntax • • • • SHR reg, count (immediate) SHR reg, CL (count in register) Moves the left operand a bit position to the right as many times as specified by count or CL The empty positions are filled with 0’s The lower order bit is stored in the C flag The most efficient way to divide by 2! Register SHR C Shift arithmetic right • Syntax: SAR reg, count SAR reg, CL • Moves each bit of the operant one position to the right as many times as specified by count/CL • Lower order bit shifts to the carry flag • High order bit is replicated Register SAR C Shift arithmetic right • Main effect is to perform a signed division by a power of two MOV AX, -15 SAR AX, 1 • ; resulting AX = -8 In 80286 and later SAR can be used to sign extend one register into another MOV AH, AL SAR AH, 7 ; assume AL = 1111 0001 ; AX = 1111 1111 1111 0001 Rotate through carry L/R • Syntax: • • • • • RCL RCL reg, count (immediate) RCL reg, CL (count in register) Rotate bits to the left through the carry flag Bit in the carry flag is written back to bit 0 Syntax: RCR reg, count (immediate) RCR reg, CL (count in register) Rotate bits to the right through the carry flag Bit in the carry flag is written back to H.O. bit RCR Rotate left/right • Syntax: • • • • • ROL ROL reg, count (immediate) ROL reg, CL (count in register) Rotate bits to the left H.O. bit goes to the L.O. bit and the carry flag Syntax: ROR reg, count (immediate) ROR reg, CL (count in register) Rotate bits to the right L.O. bit goes to the H.O. bit and the carry flag ROR Examples mov ax,3 mov bx,5 or ax,9 and ax,10101010b xor ax,0FFh neg ax not ax or ax,1 shl ax,1 shr ax,1 ror ax,1 rol ax,1 mov cl,3 shr ax,cl mov cl,3 shl bx,cl ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Initial register values ax <- ax | 0000 1001 ax <- ax & 1010 1010 ax <- ax ^ 1111 1111 ax <- (-ax) ax <- (~ax) ax <- ax | 0000 0001 logical shift left by 1 bit logical shift right by 1 bit rotate right (LSB=MSB) rotate left (MSB=LSB) Use CL to shift 3 bits Divide AX by 8 Use CL to shift 3 bits Multiply BX by 8 AX BX AX AX AX AX AX AX AX AX AX AX CL AX CL BX = = = = = = = = = = = = = = = = 0000 0000 0000 0000 0000 1111 0000 0000 0000 0000 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1111 0000 0000 0001 0000 0000 0000 0011 0000 0011 0000 0000 0000 0000 0000 1111 0000 1111 1111 1110 1111 0111 1111 0011 0101 1011 1010 0101 1011 0100 0101 1010 0101 1010 0101 0001 1110 0010 1000 Addition • Syntax: ADD A,B – A, B can be register or memory, but not both memory – B can also be immediate data • Examples – – – – – ADD AX, BX ADD AX, 5h ADD [BX], AX ADD AX, [BX] ADD DI, MYVAR ; register addition ; immediate addition ; addition to memory location ; memory location added to register ; memory offset added to the register • Flags modified: S, C, Z, O, A, P Examples ; multiply AX by the decimal 10 (1010b) ; (multiply by 2 and 8, then add results) shl mov shl add ax, bx, ax, ax, 1 ax 2 bx ; ; ; ; AX x 2 save 2AX 2 x (original AX) x 4 = 8 x (orig AX) 2AX + 8AX = 10AX ; multiply AX by decimal 18 (10010b) ; (multiply by 2 and 16, then add results) shl mov shl add ax, bx, ax, ax, 1 ax 3 bx ; ; ; ; AX x 2 save 2AX 2AX x 2 x 2 x 2 = 16AX 2AX + 16AX = 18AX Increment • Syntax: INC A – A can be register or memory location • Examples: – INC AX – INC byte [BX] – INC word [BX] ; AX=AX+1 ; memory location increased by 1 ; memory location increased by 1 • Flags modified: S, Z, O, A, P • But not the carry flag! Add with carry • Syntax: ADC A,B – A, B can be registers or memory – B can also be immediate • Function: A = A + B + carry flag • Used to add numbers larger than 16 bits (in 16-bit mode) or larger than 32 bits in (32-bit mode) • Examples – ADD AX,CX – ADC BX,DX ; produces a 32-bit sum ; of BX:AX + DX:CX -> BX:AX • Flags modified: S, C, A, Z, O, P Subtraction • Syntax: SUB A,B – A, B can be register or memory (not both memory) – B can be immediate • Function: A=A-B – Carry flag is interpreted as a borrow request from H.O. bit • • Flags modified S, C, A, Z, P, O Example: MOV CH, 22h SUB CH, 34h ; result = -12h, S=1 (negative), Z=0, C=1 ; (borrow from high order bit), P=0 (even ; parity) Decrement • Syntax: DEC A – A can be register or memory • Function: A=A-1 • Examples – DEC AX ; AX=AX-1 – DEC BYTE [BX] ; memory location decreased by 1 – DEC WORD [BX] ; memory location decreased by 1 • Flags modified: S, A, Z, P, O • Carry flag not modified! Subtract with borrow • Syntax: SBB A,B – A, B can be register or memory (not both memory) – B can be immediate • Function: A=A - B - carry flag – Used to subtract numbers which are wider than 16 bits (in 16-bit mode) or wider than 32 bits (in 32-bit mode) • Flags modified S, C, A, Z, P, O • Examples: SUB AX, DI SBB BX, SI ; this subtracts the 32-bit numbers ; BX:AX-SI:DI -> BX:AX The carry flag • Indicates a carry from the H.O. bit after addition or a borrow after subtraction • Carry is set when an unsigned number goes out of range • Example (8 bit operands) – FFh + 01h = 00h with C=1 – 02h – 03h = FFh with C=1 The overflow flag • Condition set when signed numbers go out of range • Example (8 bit operands) – – 7Fh + 01h = 80h (expected +128 but got –128) 80h – 01h = 7Fh (expected –127 but got +127) Overflows and carries mov ax,0fffeh add ax,3 ; 65534 interpreted as unsigned ; C = 1, O = 0 --Unsigned Overflow Condition mov ax,0FFFEh add ax,3 ; -2 interpreted as signed ; C = 1, O = 0 --Okay as signed mov bx,07FFFh add bx,1 ; 32767 interpreted as signed ; C = 0, O = 1 --Signed Overflow Condition mov bx,07FFFh add bx,1 ; 32767 interpreted as unsigned ; C = 0, O = 1 --Okay as unsigned mov ax,07h add ax,03h ; 7 interpreted as either signed or unsigned ; C = 0, O = 0 --Okay as either CMP - Compare • Analogous to TEST instruction, but for arithmetic operands • Performs a SUB on its operands but does not modify its destination • It sets the Flags just as SUB would • Useful to arithmetically compare two operands prior to making a conditional branch (jump)