2

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

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
nit17
  • 47
  • 5
  • See also [this answer](https://stackoverflow.com/a/58768040/417501) addressing different strategies. – fuz Dec 10 '20 at 12:35

1 Answers1

3

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).

Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
  • 3
    Alternatively, shift left by the number of places you want to sign extend, then shift right arithmetically to copy the sign bit. – fuz Nov 18 '20 at 12:18
  • 1
    "...**not** from 12-bit to 16-bit instead of 8-bit as source..." Is this sentence correct? Why the word **not**? – Sep Roland Nov 18 '20 at 18:35
  • @SepRoland Thanks. A mistake of mine. I'll correct it. – Martin Rosenau Nov 18 '20 at 19:19
  • 1
    @fuz On an 8088 or 8086 a shift operation by N bits is a rather slow operation because those CPUs internally performed 1-bit shifts in a loop. And the question: "without `movsx`" makes only sense to me if the code should work on such old CPUs, too. – Martin Rosenau Nov 18 '20 at 19:22
  • 2
    Alternatively: `XOR AX, 0x800; SUB AX, 0x800` – njuffa Nov 18 '20 at 19:38
  • @njuffa: Oh cool, that trick might potentially be useful for SIMD sign-extension within vector elements, sometimes cheaper than shift left / arithmetic-right. (Even if SSE4.1 `pmovsxbd` or whatever is available, you sometimes want to operate "in lane", especially with AVX2) – Peter Cordes Nov 18 '20 at 21:13