What does the MOVZBL instruction do in IA-32 AT&T syntax?

80,522

Solution 1

AT&T syntax splits the movzx Intel instruction mnemonic into different mnemonics for different source sizes (movzb vs. movzw). In Intel syntax, it's:

movzx eax, byte ptr [eax+ecx+1]

i.e. load a byte from memory at eax+ecx+1 and zero-extend to full register.

BTW, most GNU tools now have a switch or a config option to prefer Intel syntax. (Such as objdump -Mintel or gcc -S -masm=intel, although the latter affects the syntax used when compiling inline-asm). I would certainly recommend to look into it, if you don't do AT&T assembly for living. See also the tag wiki for more docs and guides.

Solution 2

Minimal example

mov $0x01234567, %eax
mov $1, %bl
movzbl %bl, %eax
/* %eax == 0000 0001 */

mov $0x01234567, %eax
mov $-1, %bl
movzbl %bl, %eax
/* %eax == 0000 00FF */

Runanble GitHub upstream with assertions.

The mnemonic is:

  • MOV
  • Zero extend
  • Byte (8-bit)
  • to Long (32-bit)

There are also versions for other sizes:

  • movzbw: Byte (8-bit) to Word (16-bit)
  • movzwl: Word (16-bit) to Long (32-bit)

Like most GAS instructions, you can omit the last size character when dealing with registers:

movzb %bl, %eax

but I cannot understand why we can't omit the before last letter, e.g. the following fails:

movz %bl, %eax

Why not just deduce it from the size of the operands when they are registers as for mov and Intel syntax?

And if you use registers of the wrong size, it fails to compile e.g.:

movzb %ax, %eax
Share:
80,522

Related videos on Youtube

Peter Cordes
Author by

Peter Cordes

GNU/Linux hacker and command line junkie. Primary maintainer of the Stackoverflow x86 tag wiki. I like efficient code, and knowing how things really work. I mostly use C/C++ (and perl/bash) on Linux, but I mostly look at assembly-language stuff on SO because it's more interesting to me, and there are fewer people posting good asm answers. (profile pic is from https://xkcd.com/386/, and describes me perfectly. Incomplete answers/explanations make me crazy.)

Updated on July 23, 2020

Comments

  • Peter Cordes
    Peter Cordes almost 4 years

    What exactly does this instruction do?

    movzbl  0x01(%eax,%ecx), %eax
    
    • Ciro Santilli OurBigBook.com
      Ciro Santilli OurBigBook.com about 9 years
    • Peter Cordes
      Peter Cordes almost 4 years
      @Waqar: I don't think your edit was an improvement, and seems too small to be worth bumping the question for. If you're going to add a space, I'd only add one between the two operands, not also inside the addressing mode. It's totally normal to write AT&T addressing modes without spaces since there are already commas and the allowed things are so rigid. So I'd have written movzbl 1(%eax,%ecx), %eax (that's the formatting GCC's asm output uses: godbolt.org/z/E4r9dP). This might have been literal compiler output or disassembly someone copy/pasted, with that spacing.
    • Waqar
      Waqar almost 4 years
      Alright, I will keep this in mind for future edits.
  • Admin
    Admin about 12 years
    Understood: this will load the byte from %eax + %ecx + 1 address and expand it to long with a leading zeros. Thanks a lot!
  • Peter Cordes
    Peter Cordes almost 8 years
    If you look at the opcodes, the "operand size" controls the size of the destination but there are different opcodes for different sizes of source. So it makes sense for gas to treat movzb as a separate instruction from movzw. (For sign-extension, AMD even added a new Intel-syntax mnemonic for movsxd r64, r/m32 instead of further overloading movsx. IDK why.)
  • Marius Gedminas
    Marius Gedminas over 5 years
    Assuming I'm looking at a movzbl in 64-bit x86_64 code, would "zero-extend to full register" refer to %eax, or the full %rax?
  • Igor Skochinsky
    Igor Skochinsky over 5 years
    @MariusGedminas you can probably use rax explicitly with movzbq but any operation on a 32-bit register zeroes out the top 32 bits, so in effect movzbl to eax will extend to rax.
  • Marius Gedminas
    Marius Gedminas over 5 years
    @IgorSkochinsky Thank you! (I was looking at a disassembly output of a function that somehow managed a 32-bit signed overflow while mixing 64-bit unsigned and double arithmetic. movzbl was not the culprit.)