110 likes | 267 Views
Emulating ‘MUL’. How multiplication of unsigned integers can be performed in software. Hardware support absent?. The earliest microprocessors (from Intel, Zilog, and others) did not implement the multiplication instructions – that operation would have had to be done in software
E N D
Emulating ‘MUL’ How multiplication of unsigned integers can be performed in software
Hardware support absent? • The earliest microprocessors (from Intel, Zilog, and others) did not implement the multiplication instructions – that operation would have had to be done in software • Even with our Core-2 Quad processor, there is an ultimate limit on the sizes of integers that can be multiplied using the processor’s built-in ‘multiply’ instructions
Multiplying with Base Ten • Here’s how we learn to multiply multi-digit integers using ordinary ‘decimal’ notation 8765 multiplicand x 4321 multiplier ------------------ 8765 partial product 17530 partial product 26295 partial product + 35060 partial product ------------------ 37873565 product
Analogy with Base Ten • When multiplying multi-digit integers using ‘binary’ notation, we apply the same idea 1001 multiplicand (=9) x 1011 multiplier (=11) ------------------ 1001 partial product 1001 partial product 0000 partial product + 1001 partial product ------------------ 1100011 product (=99)
Some observations… • With ‘binary’ multiplication of two N-digit values, the product can require 2N-digits • Each ‘partial product’ is either zero or is equal to the value of the ‘multiplicand’ • Succeeding partial products are ‘shifted’ • So if we want to ‘emulate’ multiplication of unsigned binary integers using software, we must implement these observations
8-bit case • The smallest case to consider is using the ‘mul’ instruction to compute the product of 8-bit values, say in registers AL and BL .section .data number1: .byte 100 number2: .byte 200 product: .word 0 .section .text mov number1, %al mov number2, %bl mul %bl mov %ax, product
Doing it by hand 100 = 0x64 = 01100100 (binary) 01100100 AL 200 = 0xC8 = 11001000 (binary) 11001000 BL 00000000 (BL x 0) 00000000 (BL x 0) 11001000 (BL x 1) 00000000 (BL x 0) 00000000 (BL x 0) 11001000 (BL x 1) 11001000 (BL x 1) + 00000000 (BL x 0) ------------------------------------- 0100111000100000 20000 = 0x4E20 = 0100111000100000 (binary) 01001110 00100000 AX
Using x86 instructions .section .text softmulb: push %rcx # save caller’s count-register sub %ah, %ah # zero-extend AL to (CF:AH:AL) mov $9, %rcx # number of bits in (CF:AH) nxbit8: rcr $1, %ax # next multiplier-bit to Carry-Flag jnc noadd # skip addition if CF-bit is zero add %bl, %ah # else add the multiplicand noadd8: loop nxbit8 # go back to shift in next CF-bit sub %ah, %cl # set CF-bit if 8-bits exceeded pop %rcx # recover caller’s count-register ret
Visual depiction ROR $1, %AX CF AH AL 0 00000000 multiplier 17-bit value gets ‘rotated’ 1-place to the right BL multiplicand then multiplicand is added to AH (unless CF =0)
Exhaustive testing • We can insert ‘inline assembly language’ in a C++ program to construct a loop that checks our software multiply operation against every case of the CPU’s ‘mul’ • Our test-program is names ‘multest.cpp’ • You can compile it like this: $ g++ multest.cpp softmulb.s -o multest
In-class exercises • Can you write a ‘software’ emulation for the CPU’s 16-bit multiply operation? mul %bx • Can you write a ‘software’ emulation for the CPU’s 32-bit multiply operation? mul %ebx