MULTIPLICATION, DIVISION AND NUMERICAL CONVERSIONS We will first study the basic instructions for doing multiplications and divisions We then use these instructions to 1. Convert a string of ASCII digits into binary number that this string represents 2. Convert a binary number (stored in some register) its a string of ASCII digits that represents its numerical value We will also use the XLAT instruction to perform character encoding
Integer Multiplication Multiplication depends on the interpretation 1. No interpretation: FFh 2h =?? 2. Signed interpretation: -1 2 = -2 3. Unsigned interpretation: 255 2 = 510 We have two different multiplication instructions MUL Source ;for unsigned multiplication IMUL Source ;for signed multiplication Where Source must be either Mem or Reg 1. Source is being multiplied by AL AX if Source is of type BYTE if Source is of type WORD EAX if Source is of type DWORD 2. The result of MUL/IMUL is stored in AX DX:AX if Source is of type BYTE if Source is of type WORD EDX:EAX if Source is of type DWORD
Integer Multiplication (Continued) AL = 80h and BL = FFh MUL BL 32640 7F 80 1 IMUL BL 128 00 80 1 Instruction Result DX AX CF/OF There is always enough storage to hold the result of MUL/IMUL. Nevertheless, CF = OF = 1 iff the result cannot be contained within the least significant half (LSH) of its storage location 1. LSH = AL if Source is of type BYTE 2. LSH = AX if Source is of type WORD 3. LSH = EAX if Source is of type DWORD CF = OF = 0 iff 1. The most significant half (MSH) is 0, for MUL 2. MSH is the sign extension of the LSH, for IMUL AX = 1h and BX = FFFFh MUL BX 65535 0000 FFFF 0 IMUL BX -1 FFFF FFFF 0 AX = FFFFh and BX = FFFFh MUL BX 4294836225 FFFE 0001 1 IMUL BX 1 0000 0001 0 AL = 30h and BL = 4h MUL BL 192 00 C0 0 IMUL BL 192 00 C0 1
Two-Operand Form for IMUL IMUL Destination, Source multiplies Source by Destination Source can be Imm, Mem or Reg, and Destination must be Reg16 or Reg32 The product is stored (only) into Destination. other registers are changed No MOV EAX, 1 ;EAX = 00000001h IMUL AX, -1 ;EAX = 0000FFFFh, CF = OF = 0 MOV EAX, 100h ;EAX = 2 8 IMUL AX, 100h ;EAX = 00000000h, CF = OF = 1 MOV EAX, 100h IMUL EAX, 100h ;EAX = 00010000h, CF = OF = 0 Exercise #1 Give the hexadecimal content of AX and the values of CF and OF immediately after the execution of each instruction below 1. IMUL AH when AX = 0FE02h 2. MUL BH when AL = 8Eh and BH = 10h 3. IMUL BH when AL = 9Dh and BH = 10h 4. IMUL AX, 0FFh when AX = 0FFh
Integer Division Notation for integer division 1. Ex: 7 2 = (3, 1) 2. Dividend Divisor = (Quotient, Remainder) We have two different division instructions Div Divisor ;for unsigned division IDIV Division ;for signed division Where Divisor must be either Mem or Reg Convention for IDIV: the remainder has always the same sign as the dividend. Ex: 5 2 = ( 2, 1) ;not ( 3, 1) The divisor determines what will hold the dividend, the quotient and the remainder Divisor Dividend Quotient Remainder BYTE WORD DWORD AX DX:AX EDX:EAX AL AX EAX AH DX EDX The effects on flags is undefined
Integer Division (Continued) We have a divide overflow whenever the quotient cannot be contained in its destination (AL if divisor is BYTE... ) Execution then traps into the OS which displays a message on screen and terminates the program DX = 0000h, AX = 0005h, BX = FFFEh DIV BX 0 5 0000 0005 IDIV BX -2 1 FFFE 0001 DX = FFFFh, AX = FFFBh, BX = 0002h DIV BX -2-1 FFFE FFFF IDIV BX Divide Overflow AX = 0007h and BX = FFFEh DIV BL 0 7 00 07 IDIV BL -3 1 FD 01 AX = 00FBh and BX = 0CFFh DIV BL 0 251 00 FB IDIV BL Divide Overflow Instruction Quotient Remainder AX DX Exercise #2 Give the hexadecimal content of AX immediately after the execution of each instruction below or indicate if there is a divide overflow 1. IDIV BL when AX = 0FFFBh and BL = 0FEh 2. IDIV BL when AX = 0080h and BL = 0FFh 3. DIV BL when AX = 7FFFh and BL = 08h
Preparing for a Division Recall that for a 1. BYTE divisor: the dividend is in AX 2. WORD divisor: the dividend is in DX:AX 3. DWORD divisor: the dividend is in EDX:EAX If the dividend occupies only its LSH we must prepare its MSH for a division 1. For DIV: MSH must be 0 2. For IDIV: MSH must be the sign extension of the LSH Preparing for IDIV To fill the MSH of the dividend with the sign of its LSF, use 1. CBW (Convert Byte to Word) fills AH with the sign of AL 2. CWD (Convert Word to Double-Word fills DX with the sign of AX 3. CDQ (Convert Double-Word to Quad-Word) fills EDX with the sign of EAX
Preparing for DIV or IDIV Sign extension (recall): 1. If AX = 8AC0h then CWD sets DX to FFFFh 2. If AX = 7F12h then CWD sets DX to 0000h To divide the unsigned number in AX by the unsigned number in BX, you must do XOR DX, DX ;to fill DX with 0 DIV BX To divide the signed number in AX by the signed number in BX, you must do CWD IDIV BX ;to fill DX with sign extension of AX Never assign the MSH of the dividend to zero before performing IDIV
The XLAT Instruction XLAT (no operand) basic tool for character translation Upon execution of XLAT, the byte pointed by EBX + AL is moved to AL.data Table DB 0123456789ABCDEF.code MOV EBX, OFFSET Table MOV AL, 0Ah XLAT ;AL = A = 41h ;converts from binary to ASCII ;code of hexadecimal digit Character Encoding This is a table to encode numerical and alphabetical characters.data CodeTable DB 0123456789ABCDEF DB 48 DUP(0) ;no translation DB 4590821367 ;ASCII codes 48--57 DB 7 DUP(0) ;no translation DB GVHZUSOBMIKPJCADLFTYEQNWXR DB 6 DUP(0) ;no translation DB gvhzusobmikpjcadlftyeqnwxr DB 133 DUP(0) ;no translation
Character Encoding This is a code snippet to encode (only) numerical and alphabetical characters.data CodeTable DB 0123456789ABCDEF DB 48 DUP(0) ;no translation DB 4590821367 ;ASCII codes 48--57 DB 7 DUP(0) ;no translation DB GVHZUSOBMIKPJCADLFTYEQNWXR DB 6 DUP(0) ;no translation DB gvhzusobmikpjcadlftyeqnwxr DB 133 DUP(0) ;no translation.code MOV EBX, OFFSET CodeTable next char: GETCH ;character in AL MOV EDX, EAX ;save original in DL XLAT ;translates character in AL CMP AL, 0 ;not translatable? JE put char ;then write original MOV EDX, EAX ;else write translation put char: PUTCH EDX ;write DL to output JMP next char
Binary to ASCII Conversion We want to convert a binary number into the string of ASCII digits that represents its unsigned value (for display) Ex: if AX = 4096, to generate the string 4096 we divide by 10 until the quotient is 0 Dividend 10 = Quotient Remainder 4096 10 = 409 6 409 10 = 40 9 40 10 = 4 0 4 10 = 0 4 The same method can be used to obtain the ASCII string of digits with respect to any base Ex: if AX = 10C4 = 4292, to generate the string 10C4 we divide by 16 until the quotient is 0 Dividend 16 = Quotient Remainder 4292 16 = 268 4 4 268 16 = 16 12 c 16 16 = 1 0 0 1 16 = 0 1 1
Binary to ASCII Conversion (Continued) The Wuint procedure displays the ASCII string of the unsigned value in EAX EBX contains a radix value (2 to 16) that determines the base of the displayed number The Wsint procedure displays the ASCII string of the signed value in EAX 1. Check the sign-bit. If the value is negative, perform two s complement (with NEG instruction) and display - 2. Then use the same algorithm to display the digits of the (now) positive number
Procedure Wuint Wuint PROC ;Writes a 32-bit unsigned binary ;integer to standard output ;Input parameters: EAX = value, EBX = radix ;stores each digit in the stack PUSHA CMP EBX, 2 JAE wu cont1 PUTSTR Rad err JMP wu exit wu cont1: CMP EBX, 16 JBE wu cont2 PUTSTR Rad err JMP wu exit wu cont2: MOV ESI, EBX ;save radix into ESI MOV EBX, OFFSET XTable ;translate table XOR ECX, ECX ;clear digit count L3: XOR EDX, EDX ;clear upper half of dividend DIV ESI ;divide EDX:EAX by the radix XCHG EAX, EDX ;now: EAX=remainder and EDX=quotient XLAT ;look up ASCII digit PUSH EAX ;store digit in stack XCHG EAX, EDX ;swap quotient into EAX INC ECX ;increment digit count OR EAX, EAX ;quotient = 0? JNZ L3 ;no! divide again L4: ;Display digit in stack starting with last entered POP EDX ;DL = character to be displayed PUTCH EDX ;display char in DL LOOP L4 wu exit: POPA RET XTable DB 0123456789ABCDEF ;translate table Rad err DB "Error: radix must be between 2 and 16",0 Wuint ENDP
Procedure Wsint Wsint PROC ;Writes a 32-bit signed binary ;integer to standard output ;Input parameters: EAX = value, EBX = radix ;stores each digit in the stack PUSHA CMP EBX, 2 JAE ws cont1 PUTSTR Rad err JMP ws exit ws cont1: CMP EBX, 16 JBE ws cont2 PUTSTR Rad err JMP ws exit ws cont2: MOV ESI, EBX ;save radix into ESI MOV EBX, OFFSET XTable ;translate table XOR ECX, ECX ;clear digit count TEST EAX, 80000000h ;is the signed value ;in AX negative? JZ L3 ;no! so display positive value PUTCH - NEG EAX ;perform two s complement L3: XOR EDX, EDX ;clear upper half of dividend DIV ESI ;divide EDX:EAX by the radix XCHG EAX, EDX ;now: EAX=remainder and EDX=quotient XLAT ;look up ASCII digit PUSH EAX ;store digit in stack XCHG EAX, EDX ;swap quotient into EAX INC ECX ;increment digit count OR EAX, EAX ;quotient = 0? JNZ L3 ;no! divide again L4: ;Display digit in stack starting with last entered POP EDX ;DL = character to be displayed PUTCH EDX ;display char in DL LOOP L4 ws exit: POPA RET XTable DB 0123456789ABCDEF ;translate table Rad err DB "Error: radix must be between 2 and 16",0 Wsint ENDP
ASCII to Binary Conversion To convert a sequence of ASCII digits into its numerical value: From left to right: for each digit, we multiply the previous product by the base and add the digit to the current product. Previous product is set to 0, initially Ex: to convert 4096 into its base-10 value Previous 10 + Digit = Current 0 10 + 4 = 4 4 10 + 0 = 40 40 10 + 9 = 409 409 10 + 6 = 4096 Final value The same method can be used to obtain the ASCII string of digits with respect to any base Be careful when doing addition and multiplication in a base other than 10. Review you 03-60-265 notes
ASCII to Binary Conversion (Continued) The Rint procedure reads a string of ASCII decimal digits and stores the base 10 numerical value into EAX 1. For signed numbers: the sequence of digits can be preceded by a sign 2. Checks for overflows at each multiplication and addition The program below uses both Rint and Wsint.386.model Flat include Cs266.inc.data Msg1 DB "Enter an integer: ", 0 Msg2 DB "EAX = ", 0.code main: PUTSTR Msg1 CALL Rint PUTSTR Msg2 MOV EBX 10 CALL Wsint RET ;from main include Wsint.asm include Rint.asm End
Procedure Rint Rint PROC ;Reads a signed integer from standard input ;The first sequence of decimal ;digits determines the number ;all other entries are ignored ;Input: none (only keyboard input) ;Output: EAX contains the number PUSH EBX PUSH ECX PUSH EDX PUSH ESI PUSH EDI MOV EDI, 1 ;assume that the number is positive M1: GETCH ;char in AL CMP AL, + JE M1 ;read next char CMP AL, - JNE M2 MOV EDI, -1 ;the number is negative JMP M1 ;read next char M2: CALL IsDecDigit ;ZF=1 iff AL contains a dec-digit JNE M1 ;read a char until a digit is found ;a Dec digit as been entered ;perform signed multiplication ;of positive numbers ;until a non-dec-digit is entered MOV EBX, 10 ;EBX is the multiplier AND EAX, 0Fh ;convert to numerical value ;EAX holds the product ;initially EAX = first number entered M3: PUSH EAX ;save product on stack GETCH CALL IsDecDigit JZ M4 POP EAX JMP done ;we are done
Procedure Rint (Continued) M4: MOV ECX, EAX ;save digit in CL AND ECX, 0Fh ;convert to numerical value POP EAX ;recover the product IMUL EBX ;EDX:EAX = EAX 10 JO A6 ;exit if overflow ADD EAX, ECX ;add to product JO A6 ;exit if overflow JMP M3 done: IMUL EDI ;EDX:EAX = EAX * sign ;no possibility of overflow here JMP exit A6: PUTSTR Overflow msg exit: POP EDI POP ESI POP EDX POP ECX POP EBX RET Overflow msg DB integer overflow,10,0 Rint ENDP IsDecDigit PROC ;sets ZF = 1 iff the character ;in AL is a decimal digit. CMP AL, 0 JB B1 CMP AL, 9 JA B1 TEST AX, 0 ;set ZF=1 B1: RET IsDecDigit ENDP