Search code examples
cgccassemblyobjdump

Assembly instruction addl using byte instead of long


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?


Solution

  • 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