Search code examples
assemblybinaryx86-16sign-extension

Zero/Sign extension in assembly without using MOVZX/MOVSX


I'm trying to do a zero or sign extension but without using MOVZX or MOVSX.
I basically want to mimic the said commands, but not use them. Is there a way to do it?
To add 0 from the left there's SHR but I'm not quite sure that it works the same because it changes the value...

I'm using Assembly 8086


Solution

  • All x86-16 CPUs provide the CBW (8-bit to 16-bit) and CWD (16-bit to 32-bit) instructions.

    If you want to do a "generic" sign extension (e.g. from 12-bit to 16-bit instead of from 8-bit to 16-bit), you might use the following algorithm that works on any CPU:

    • Perform an AND to get the highest bit of the word to be extended
    • Subtract the result from the original value twice or:
    • Shift the result left by one and subtract it once from the original value

    Example: Sign-extending AX from 12-bit to 16-bit:

    ; Ensure that the value is really a 12-bit value
    AND AX, 0xFFF
    ; Extract the highest bit
    MOV CX, AX
    AND CX, 0x800
    ; Subtract that value twice
    SUB AX, CX
    SUB AX, CX
    

    The code above may be simplified by working on the high byte of AX only (e.g. AND AH, 0xF instead of AND AX, 0xFFF).