??? 03/14/18 18:32 Read: times |
#190873 - 16 * 16 bit |
Hi,
Here is a nice piece of code to multiply two 16 bit operands, signed and unsigned. Can someone please explain me the methodology used in the calculation loop. That is from label "M16_Loop:" to "M16_Calculations done". All the rest of the code is clear to me except that part. Thanks a lot! ;---------------------------------------------------------------------------------------- ;Function name: mul_16x16_signed ;Description..: Multiplies 2 signed 16-bit operands resulting in a signed 32-bit number. ; Control flag MathLib_Res1Neg is set with negative result. ; ; ;Function name: mul_16x16_unsigned ;Description..: Multiplies 2 unsigned 16-bit operands resulting in a unsigned 32-bit number. ; ; ;Function name: mul_16x16_signed_op1 ;Description..: Multiplies signed 16-bit operand (op1) by ; unsigned 16-bit operand (op2) resulting in a signed 32-bit number. ; Control flag MathLib_Res1Neg is set with negative result. ; ; ;Inputs: Operand 1 HB = MathLib_Op1+0 ; LB = MathLib_Op1+1 ; ; Operand 2 HB = MathLib_Op2+0 ; LB = MathLib_Op2+1 ; ;Output: Result HB = MathLib_Res1+0 ; MathLib_Res1+1 ; MathLib_Res1+2 ; LB = MathLib_Res1+3 ; ; Negative result: MathLib_Res1Neg = 1 ;------------------------------------------------------------------------------------ ; mul_16x16_signed: mov MathLib_Flags,#0 ;Clear control flags push b ;Save used registers by routine mov b,#16 ;Initialize loop counter jmp M16_signed_init mul_16x16_unsigned: mov MathLib_Flags,#0 ;Clear control flags push b ;Save used registers by routine mov b,#16 ;Initialize loop counter jmp M16_unsigned_init mul_16x16_signed_op1: mov MathLib_Flags,#0 ;Clear control flags push b ;Save used registers by routine mov b,#16 ;Initialize loop counter jmp M16_signed_op1_init ;---------------------------------------------------------------------------------------- ;Do Calculation ; M16_signed_init: mov a,MathLib_Op2+0 ;Is the signed operand 2 negative? rlc a jnc M16_000 ;If not, skip complementing cpl MathLib_NegateResult ;Toggle negate result flag xrl MathLib_Op2+1,#0FFh ;Complement operand 2 xrl MathLib_Op2+0,#0FFh mov a,MathLib_Op2+1 ;Increment operand 2 LB add a,#1 mov MathLib_Op2+1,a jnc M16_000 ;If carry also increment LB inc MathLib_Op2+0 ;Propagate carry into HB M16_000: M16_signed_op1_init: mov a,MathLib_Op1+0 ;Is the signed operand 1 negative? rlc a jnc M16_001 ;If not, skip complementing cpl MathLib_NegateResult ;Toggle negate result flag xrl MathLib_Op1+1,#0FFh ;Complement operand 1 xrl MathLib_Op1+0,#0FFh mov a,MathLib_Op1+1 ;Increment operand 1 LB add a,#1 mov MathLib_Op1+1,a jnc M16_001 ;If carry also increment LB inc MathLib_Op1+0 ;Propagate carry into HB M16_001: M16_unsigned_init: ;Initialize result 'register' mov MathLib_Res1+3,MathLib_Op2+1 ;Put 16-bit multiplier in byte 3 of product/multiplier mov MathLib_Res1+2,MathLib_Op2+0 ;Put 16-bit multiplier in byte 2 of product/multiplier mov MathLib_Res1+1,#0 ; Clear byte 1 of product/multiplier mov MathLib_Res1+0,#0 ; Clear byte 0 of product/multiplier M16_loop: mov a,MathLib_Res1+3 ;Is low bit of multiplier set? rrc a jnc M16_DoShift M16_DoAdd: mov a,MathLib_Res1+1 ;Upper 16 bits of product/multiplier += multiplicand add a,MathLib_Op1+1 ;Add LSB of multiplicand mov MathLib_Res1+1,a mov a,MathLib_Res1+0 addc a,MathLib_Op1+0 ;Add MSB of multiplicand mov MathLib_Res1+0,a M16_DoShift: mov a,MathLib_Res1+0 ;Shift entire product/multiplier right once rrc a mov MathLib_Res1+0,a mov a,MathLib_Res1+1 rrc a mov MathLib_Res1+1,a mov a,MathLib_Res1+2 rrc a mov MathLib_Res1+2,a mov a,MathLib_Res1+3 rrc a mov MathLib_Res1+3,a djnz b,M16_loop ;Check all loops done M16_CalculationsDone: pop b ;Restore registers used by routine M16_CheckNegateResult: jnb MathLib_NegateResult,M16_End ;Should the answer be negative? setb MathLib_Res1Neg ;Set bit negative result xrl MathLib_Res1+3,#0FFh ;Yes, complement the answer xrl MathLib_Res1+2,#0FFh xrl MathLib_Res1+1,#0FFh xrl MathLib_Res1+0,#0FFh mov a,MathLib_Res1+3 ;Increment result LB add a,#1 mov MathLib_Res1+3,a jnc M16_End ;No carry: we're done mov a,MathLib_Res1+2 ;Propagate carry into byte 2 addc a,#0 mov MathLib_Res1+2,a jnc M16_End ;No carry: we're done mov a,MathLib_Res1+1 ;Propagate carry into byte 1 addc a,#0 mov MathLib_Res1+1,a jnc M16_End ;No carry: we're done mov a,MathLib_Res1+0 ;Propagate carry into byte 0 addc a,#0 mov MathLib_Res1+0,a M16_End: ret |