assemblybootloadergnu-assembler

Assembly code fail when I add a jump before rept


I have the following assembled but when ever I uncomment the jmp or je it fail with 11: Error: bad or irreducible absolute expression

_start:
    mov $0x0e, %ah  
    mov $'a', %al   
_loop:
    int $0x10
    cmp $'z',%al
    je _exit
    inc %al
    #jmp _loop
_exit:
.rept 510 - (. - _start) # HERE IS LINE 11 WHERE IT INDICATE ERROR
    .byte 0
.endr
.byte 0x55, 0xaa
                                                                            

Assembler version : GNU assembler version 2.26.1 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.26.1

Command line to assemble : as -o boot-gas.o boot-gas.s


Solution

  • GAS docs describe it as a one-pass assembler; it only parses the source once, and builds some internal data structures. It does make multiple passes over those for things like branch-length optimization (whether 2-byte jcc rel8 is in range or if it needs 6-byte jcc rel32. Or if you'd used .code16 like you need for a 16-bit MBR boot sector, 4-byte. Same for jmp rel8 (2 bytes) vs. jmp rel16/32 (3 / 5 bytes)).

    It seems that the argument to .rept must be computable early, before those later passes. That makes sense, as .rept can repeat arbitrary code including branches and .p2align directives which themselves can change size.

    . - _start isn't a constant that's ready early enough when there are variable-length instructions like jumps between _start and the current position.

    But .space 510-(.-_start) doesn't need its operand ready until later, so use it instead. See Calculating padding length with GAS AT&T directives for a boot sector?

    You can specify a different byte to fill with if you want; the default is 0 like you were using with .byte. https://sourceware.org/binutils/docs/as/Space.html