Search code examples
visual-studioassemblyx86multiplicationtwos-complement

I still don't get how IMUL works in Assembly


I am a begginer with assembly i just started learning it and i don't get how the instruction IMUL really works

For example i'm working on this piece of code on visual studio:


Mat = 0A2A(hexadecimal)

__asm {

    MOV AX, Mat
    AND AL,7Ch
    OR AL,83h
    XOR BL,BL
    SUB BL,2
    IMUL BL
    MOV Ris5,AX
}

the result in Ris5 should be 00AA (in hexadecimal), for the first couple lines i'm all good, from the first line to 'SUB BL,2' the results are AL = AB (AX =0AAB) but then starting from IMUL i'm stuck. I know that IMUL executes a signed multiply of AL by a register or a byte or a word .. and stores the result in AX (here) but i can't find the same result (00AA)


Solution

  • MOV AX, Mat    AX = 0x0A2A  (...00101010)
    AND AL,7Ch     AX = 0x0A28  (...00101000)
    OR AL,83h      AX = 0x0AAB  (...10101011)
    XOR BL,BL      BL = 0x00
    SUB BL,2       BL = 0xFE
    IMUL BL        AX = 0xFFAB * 0xFFFE = 0x00AA
    MOV Ris5,AX    Ris5 = 0x00AA
    

    When you multiply two N bit numbers the lower N bits don't care about signed vs unsigned, but as you pad the numbers then you get into signed vs unsigned multiply instructions as you will see in some instruction sets. To not lose precision you desire a 2*N number of bits result, grade school math:

       00000000aaaaaaaa
    *  00000000bbbbbbbb
    =====================
    
       AAAAAAAAAAaaaaaa
    *  BBBBBBBBBBbbbbbb
    ====================
    

    Signed vs unsigned with the Capital letter representing the sign extension

    0xAB = 171 unsigned = -85 signed

    0xFE = 254 unsigned = -2 signed

    unsigned multiply 171 * 254 = 43434 = 0xA9AA

    signed multiply -85 * -2 = 170 = 0x00AA

    The lower byte is the same as they are 8 bit operands and the sign extension doesn't come into play:

             bbbbbbbb *a[0]
            bbbbbbbb  *a[1]
           bbbbbbbb   *a[2]
          bbbbbbbb    *a[3]
         bbbbbbbb     *a[4]
        bbbbbbbb      *a[5]
       bbbbbbbb       *a[6]
    + bbbbbbbb        *a[7]
    ==================
     cyyyyyyyxxxxxxxx       
    

    If you look up the columns the x bits are not affected by the sign extension so are the same for unsigned and signed. y bits are affected as well as the carry out of the msbit c which makes up the 16th bit of the result.

    Now the tool is not complaining about this syntax, is it?

    Mat = 0A2A(hexadecimal)
    

    Without an h at the end or 0x or $ up-front that looks like octal, but the A's would cause an error if octal (or if decimal). Assuming you start with 0x0A2A, I think your understanding is solid.