2

I get the Multiplication from 8bit and 8bit register. But, when you have one in 16 bit, and one in 8bit, how do we do the conversion before multiplying:

Question : need to provide code fragments for 260*19, and print the results. I did:

mov Ax,260
mov Al,19
cbw;
Mul Ax 
PutInt Ax
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Zatom
  • 19
  • 5
  • 1
    no, `cbw` sign-extends AL into AX, overwriting your other input. Use a debugger. Take your 16-bit input in a different register, like DX (which will be overwritten by the high-half output of 16-bit `mul`). Or extend at assemble time, like `mov cx, 19` / `mul cx` – Peter Cordes Apr 12 '19 at 06:52
  • 1
    BTW, there's nothing special about MUL here, except that it and CBW both implicitly use AX. Normally you use CBW / CWD / CDQ as setup for `div`: [When and why do we sign extend and use cdq with mul/div?](//stackoverflow.com/q/36464879). But sure, if you have a number in AL you want to sign-extend, then CBW is the most efficient way, and MUL does need both inputs to be the same width. – Peter Cordes Apr 12 '19 at 06:56

1 Answers1

1
mov Ax,260
mov Al,19

The AL register is the lowest half of the AX register.

            AX
    /-----------------\
MSB xxxx xxxx xxxx xxxx LSB
    \-------/ \-------/
        AH        AL

The 2nd instruction mov al, 19 thus erroneously overwrites your 1st number.

Mul Ax 

The byte-sized mul instruction multiplies the ALregister by the specified byte-sized operand.
The word-sized mul instruction multiplies the AXregister by the specified word-sized operand.

Using mul ax then would calculate AX * AX, which is not what you wanted. You want to multiply different numbers.

Using AX together with another register like BX solves both problems.


What to do with that cbw depends on how we look at the code.

  • If you work with the numbers as immediates (260, 19), then just use a word-sized register even for the small number 19:

    mov     bx, 260
    mov     ax, 19
    mul     bx       ; Product AX * BX is in DX:AX but here DX=0
    PutInt  ax
    

    or even let the assembler do the multiplication:

    mov     ax, 260 * 19
    PutInt  ax
    
  • If the numbers come from memory (different sized variables) then you need to extend the smaller one.

    • Unsigned numbers, use mulfor unsigned multiply

      mov     bx, wNum  ; [0,65535]
      mov     al, bNum  ; [0,255]
      mov     ah, 0
      mul     bx        ; Product AX * BX is in DX:AX
      PutInt  ax
      

      I advice against using cbw in this case! Using cbw would criple all numbers from 128 upwards.

    • Signed numbers, use imulfor signed multiply

      mov     bx, wNum  ; [-32768,32767]
      mov     al, bNum  ; [-128,127]
      cbw
      imul    bx        ; Product AX * BX is in DX:AX
      PutInt  ax
      

      cbw is the right choice to extend the signed byte from AL.

Sep Roland
  • 33,889
  • 7
  • 43
  • 76