0

When I compile my assembly file (code below) I get the message Error: invalid instruction suffix for `mov' pointing to my movw instruction line. Now, I've Googled a bit and still don't understand this. My CPU is 64-bit, but since I'm clearly telling gcc to generate 32-bit code shouldn't movw be a valid instruction to move the lower 16 bits of a register? I'm copying the example almost verbatim from my book at hand.

remnux@remnux:~/Assembly$ gcc -o zx zx.s -gstabs -m32 zx.s: Assembler messages: zx.s:10: Error: invalid instruction suffix for `mov'

.code32
.section .data
myString:
  .asciz "eax is now %d\n"
.section .text
.globl main
main:
  movl $9999, %ebx
  movl $3, %eax
  movw %ax, %ebx
  pushl %ebx
  pushl %eax
  pushl %ebx
  pushl $myString
  call printf
  add $8, %esp
  popl %eax
  popl %ebx
  movzx %ax, %ebx
  pushl %ebx
  pushl %eax
  pushl %ebx
  pushl $myString
  call printf
  add $8, %esp
  call printf
  call exit
patricio2626
  • 147
  • 1
  • 3
  • 17
  • 4
    You've got a 16-bit `movw` with a 32-bit `%ebx` -- that can't work. – Chris Dodd Mar 01 '16 at 00:40
  • Hmm, the book has this example, and I was under the impression that it would only move to the lower 16 bits of register ebx. Example from the book: *****There is no guarantee that the upper part of the EBX register contains zeroes. To accomplish this, you must use two instructions: movl $0, %ebx movw %ax, %ebx****** So, you think this is a typo and they meant something like movw %ax, %bx? – patricio2626 Mar 01 '16 at 00:43
  • 1
    If your processor supports it, you can use `movzx %ax, %ebx`. This is available in ia32 (386 and later). – EOF Mar 01 '16 at 00:45
  • @EOF: right, I was just parroting the movw example to solidify understanding. – patricio2626 Mar 01 '16 at 00:46
  • 1
    @patricio2626: yes, that would be a typo in your book -- to do a 16-bit mov it needs to be `movw %ax, %bx` -- the instruction size and all the register sizes must match, or the assembler will flag it as an error. – Chris Dodd Mar 01 '16 at 00:50
  • @ChrisDodd yup, it was a typo for sure. I used movw %ax, %bx and cleaned the code up and now get the expected results: remnux@remnux:~/Assembly/zx$ ./zx ebx is now 9961475 ebx is now 3 – patricio2626 Mar 01 '16 at 00:51
  • @EOF: 386 also introduced 32bit regs in the first place, and the code already uses 32bit regs in every other instruction. It's only an issue for 16bit code, since some people are stuck with emu8086 instead of a modern CPU in 16bit mode. – Peter Cordes Mar 01 '16 at 00:51
  • @ChrisDodd if you provide that as an answer I'll accept it. I hate to answer my own question when you solved it. – patricio2626 Mar 01 '16 at 00:52
  • 1
    @patricio2626: note that `mov %eax, %ebx` is shorter and faster than `movw %ax, %bx`. It avoids a partial write of ebx. Only use 16bit instructions when you actually need truncation to 16bits (e.g. a 16bit store of the low 16.) [Often you can still use wider add/sub/mul instructions](http://stackoverflow.com/questions/34377711/which-2s-complement-integer-operations-can-be-used-without-zeroing-high-bits-in) – Peter Cordes Mar 01 '16 at 00:53
  • @PeterCordes Fair point. Sometimes I wish the most performant modern CPU available to normal consumers wasn't descended from a bad 16-bit micro. – EOF Mar 01 '16 at 00:54
  • @EOF: The instruction set does get a lot done with not too many bytes of code, or with too many instructions. Obviously it has some horrible baggage (some of my pet peeves are: `setcc r/m8` is the only option, not `r/m32`, `bt` with a memory operand is ridiculous, and shift leaves flags unmodified if count is zero, so var-count shift has an input dependency on the flags). It's nasty to decode, too, but getting more done with each insn is a good thing (decoder complexity is cheaper than a wider pipeline). [Interesting insn set proposal](http://www.agner.org/optimize/blog/read.php?i=421). – Peter Cordes Mar 01 '16 at 02:59

1 Answers1

1

Chris Dodd was right but posted a comment and not an answer. As each answer should have closure, I'm answering my own question.

I was using a 16-bit movw with a 32-bit %ebx and the example in the book was incorrect. movw will work with a 16-bit register such as %bx, or movl to move 32 bits into %ebx.

patricio2626
  • 147
  • 1
  • 3
  • 17