For MOVZBL, the low 8 bits of the destination are replaced by the source operand. the top 24 bits are set to 0. The source operand is unaffected. For MOVZBW, the low 16 bits of the destination are replaced by the source operand.
Assuming you are talking about x86, the MOVSBL instruction extends a byte (8 bits) representing a signed number to 32-bit signed number. The remaining 24 bits are zeros or ones depending on the sign so that the two's complement value remains.
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.
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:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With