I am at the moment studying the assembly code compiled from simple c programs using objdump, but this confuses me:
4004f1: c7 45 fc 02 00 00 00 movl $0x2,-0x4(%rbp)
4004f8: 83 45 fc 05 addl $0x5,-0x4(%rbp)
Doesn't the 'l' prefix in the instructions stand for long, for the movl it looks fine, but the addl seems to use a single byte for the operand, why is this?
Many instructions that operate on immediates can either have an 8 bit immediate or a 32 bit immediate (mov r/m32,i32
notably does not). The purpose of this design is likely to reduce code size. However, the immediate is implicitly sign-expanded to 32 bit. In the case of add
, opcode 83 /0
is add
with an 8 bit immediate, opcode 81 /0
is add
with a 32 bit immediate. Your assembler should automatically choose the shortest encoding. You can assemble this little snippet and then disassemble the result to observe the difference:
.byte 0x83,0xc0,0x00 # addl $0,%eax with an 8 bit immediate
.byte 0x81,0xc0,0x00,0x00,0x00,0x00 # addl $0,%eax with a 32 bit immediate