-3

Is there a way that we can rewrite the below assembly operation using only mov instruction

movzx   eax, WORD  [short_temp]
Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Arnold Asllani
  • 155
  • 1
  • 12
  • 4
    Although inefficient you can use 2 _mov_ instructions. `mov eax, 0` `mov ax, [short_temp]`. There are better ways if your question doesn't have to be interpreted literally (ie. using _only_ mov) – Michael Petch Jan 01 '17 at 01:05

2 Answers2

4

You never need to avoid movzx. If 32-bit registers like EAX are available, then your code is running on a 386 or later so movzx is supported, too.

It's by far the most efficient way to do this on an Intel CPU. movzx r32, [memory] decodes to just a load uop, with no ALU operation. The latency is the same as normal load (IIRC), so the zero extension is done for free by the load unit.

On an AMD Bulldozer-family CPU, movzx always uses an ALU port (as well as a load port when it's a memory operand), so it could in theory be faster to xor-zero EAX before using a word-load (@Downvoter's answer). This might give you one cycle lower load-use latency at the cost of larger code-size and more m-ops for the frontend to decode.

Other suggestions like doing a word-load into AX and then and eax, 0xFFFF are obviously worse, because of reading EAX after a partial-register write (of AX), and because it's a separate ALU operation that adds another cycle of latency. (xor-zeroing avoids the partial-register penalty, even on Intel P6-family CPUs.)

Community
  • 1
  • 1
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
1

Of course, easily. Just zero out eax and set ax afterwards:

XOR EAX, EAX
MOV AX, [short_temp]

If you want to obtain a word from [EAX] as you said here, just store the address to some other register beforehand:

MOV EBX, EAX
XOR EAX, EAX
MOV AX, [short_temp]

or, if that's not possible, do as @fuz proposed and clear the upper 16 bits of EAX using AND:

MOV AX, [EAX]
AND EAX, FFFFh
Community
  • 1
  • 1
cadaniluk
  • 15,027
  • 2
  • 39
  • 67
  • 1
    I have not downvoted you, but this does not meet OP's requirement as it also uses the `XOR` instruction. – fuz Dec 31 '16 at 23:17
  • what if `movzx eax, WORD [eax]` – Arnold Asllani Dec 31 '16 at 23:18
  • @fuz I cannot imagine that the OP meant use of just **one** instruction, i.e., `mov`. Why have `movzx` if it can be expressed using `mov`? – cadaniluk Dec 31 '16 at 23:19
  • 1
    No idea either, but these are OP's requirements. – fuz Dec 31 '16 at 23:20
  • 1
    @arnoldasllani Consider using `mov ax, [short_temp]` and then `and ax, FFFFj`. – fuz Dec 31 '16 at 23:20
  • @arnoldasllani Then you use `eax` for indirect addressing. Simple textual replacement that should be. – cadaniluk Dec 31 '16 at 23:22
  • @fuz `and eax, FFFFh`, isn't it? That's bigger than my solution I think because of the 4-byte immediate. – cadaniluk Dec 31 '16 at 23:24
  • Your solution doesn't work if `eax` is the index register. – fuz Dec 31 '16 at 23:39
  • 1
    xor-zeroing avoids a partial-register penalty on Intel CPUs for reading EAX after writing AX. It should definitely be preferred if you for some reason want to avoid MOVZX. I have no idea why you'd want to use only MOV instructions, but `mov eax,0` would work, too. – Peter Cordes Jan 01 '17 at 01:31
  • @fuz Fixed now. – cadaniluk Jan 01 '17 at 01:38
  • Even though `XOR` is functionally free (either because it's implemented via register renaming on modern processors, or because you can interleave it within other instructions to hide its cost on older processors), this code will actually be slower than `MOVZX` because of the 16-bit prefix required for that second `MOV` instruction. The `AND` version is even worse—there are penalties all over the place lurking there! – Cody Gray - on strike Jan 02 '17 at 11:56