What does the MOVZBL instruction do in IA-32 AT&T syntax?
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 x86 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
Related videos on Youtube
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, 2020Comments
-
Peter Cordes almost 4 years
What exactly does this instruction do?
movzbl 0x01(%eax,%ecx), %eax
-
Ciro Santilli OurBigBook.com about 9 yearssame for movsbl: stackoverflow.com/questions/7861095/…
-
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 almost 4 yearsAlright, I will keep this in mind for future edits.
-
-
Admin about 12 yearsUnderstood: this will load the byte from
%eax + %ecx + 1
address and expand it to long with a leading zeros. Thanks a lot! -
Peter Cordes almost 8 yearsIf 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 frommovzw
. (For sign-extension, AMD even added a new Intel-syntax mnemonic formovsxd r64, r/m32
instead of further overloadingmovsx
. IDK why.) -
Marius Gedminas over 5 yearsAssuming 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 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 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.)