Search code examples
assemblybit-manipulationemu8086

shl won't move bits between 2 byte groups (x86)


I have this code for calculating a factorial:

jmp start

; variables
num1 DD 0001h

start:  mov cl, al

        factorial_loop: ; cx = ax -> 1
            mov al, cl
            mul num1
            ; combine dx and ax into num1
            mov num1, dx
            shl num1, 16
            add num1, ax
        loop factorial_loop

mov ah, 0
int 16h

ret

At the start of the code I declared num1 as a 4 byte variable. Let's assume num1 is divided in 2 byte groups: num1(left) and num1(right). When I shift the bits they don't move from num1(right) to num1(left). How can I solve this?


Solution

  • You are working in 16-bit assembler, so you cannot shift a 32-bit value with a 16-bit instruction.

    shl num1, 16
    

    is implicitly the same as (not sure if your assembler supports this syntax, but you should be able to get the idea):

    shl word ptr ds:[num1], 16
    

    in 8086/80286 assembler. There is no 32-bit equivalent in 8086/80286 assembler.

    Since you appear to be working with 16-bit code, you could solve this in one of two ways:

    1) declare two 16-bit words rather than one 32-bit word, such as

    numlo dw 0     ; these are encoded exactly like num1,
    numhi dw 0     ; but are declared separately for easier use
    
    ...
    
    mov numlo,dx   ; just write to the appropriate 16-bit word
    mov numhi,ax   ; without the need to shift at all
    

    2) or apply a manual offset, such as

    mov [num1+2],dx
    mov num1,ax
    

    You will have to determine the correct syntax for your assembler for the manual offset, although the above example should be very close, based on your code.