online GAS assembler accepts AT&T syntax for movb and movw, but not movl?


I'm using to assemble x86 instructions to machine code. (Editor's note: it uses GAS in .intel_syntax noprefix mode.)

The below code throws Error: no such instruction: `movl $0xdeadbeef,0x08048c5f'

movl $0xdeadbeef,0x08048c5f

But the following assembly code works fine

movb $0xdeadbeef, 0x08048c5f
movw $0xdeadbeef, 0x08048c5f
asked on Stack Overflow Oct 13, 2014 by Kumar Vikramjeet • edited Apr 10, 2019 by Peter Cordes

2 Answers


You seem to be using AT&T syntax for your movl, but the page you link states that it wants Intel syntax.

If I understand your intention correctly, the correct syntax for the instruction you want would be;

MOV DWORD PTR ds:0x08048c5f, 0xdeadbeef

(which stores the double word value 0xdeadbeef at address 0x08048c5f)

answered on Stack Overflow Oct 13, 2014 by Joachim Isaksson

It's not just that's weird like this: it just uses GAS in .intel_syntax noprefix mode.

(So you want mov dword ptr [0x08048c5f], 0xdeadbeef as @Joachim says)

But the interesting part here is that the GNU assembler accepts movb and movw, but not movl, when in Intel-syntax mode!!

However, it's not interpreting them as AT&T syntax. In Intel-syntax, the destination is on the left, and $0xdeadbeef is a valid symbol name because it starts with a $, not a digit. GAS's .intel_syntax mode is MASM-like, where (like AT&T syntax) a bare symbol name is a memory operand.

The surprising thing is that movb is accepted as specifying byte operand-size for mov, but once we get past that, movb $0xdeadbeef, 0x08048c5f is equivalent to mov byte ptr [label], 0x5f.

Note that the 0x08048c5f constant (which you intended to be the destination address) is the immediate source operand. And it's truncated to 8 bits. GAS warns about this, but the online assembler hides the warnings that would have helped you figure out this weirdness. :(

.intel_syntax noprefix

movb $0xdeadbeef, 0x08048c5f
movw $0xdeadbeef, 0x08048c5f

On my Linux desktop with as --version = GNU assembler (GNU Binutils) 2.31.1

$ as -32 syntax.s -o syntax.o
as -32 -o syntax.o syntax.s 
syntax.s: Assembler messages:
syntax.s:3: Warning: 134515807 shortened to 95
syntax.s:4: Warning: 134515807 shortened to 35935

$ objdump -drwC -Matt syntax.o 

syntax.o:     file format elf32-i386

Disassembly of section .text:

00000000 <.text>:
   0:   c6 05 00 00 00 00 5f    movb   $0x5f,0x0        2: R_386_32     $0xdeadbeef
   7:   66 c7 05 00 00 00 00 5f 8c      movw   $0x8c5f,0x0      a: R_386_32     $0xdeadbeef

$ ld -melf_i386 syntax.o 
ld: warning: cannot find entry symbol _start; defaulting to 0000000008049000
ld: syntax.o:(.text+0x2): undefined reference to `$0xdeadbeef'
ld: syntax.o:(.text+0xa): undefined reference to `$0xdeadbeef'

Trying to link, and asking objdump to show relocations with -r in the .o, make it clear that that $0xdeadbeef is being treated as a symbol name, no different than if I'd used my_label instead.

With just the online assembler, it would be a lot harder to figure this out because it only shows you the machine code. The 00 00 00 00 for the destination address is your only clue that something weird happened.

I have no idea why movb and movw are accepted, but movl doesn't imply dword operand-size.

It's probably a GAS bug that they're accepted at all.

answered on Stack Overflow Apr 10, 2019 by Peter Cordes

User contributions licensed under CC BY-SA 3.0