Why does using jmp prevent the Clang collector from evaluating an absolute expression for .fill?

I fiddled with writing a simple toy loader (more info at the bottom of the post). The following code nasm

shows what the bootloader looked like at some point before I tried to switch to Clang. When compiled with nasm -f bin -o nasm.out boot.asm

, then run with qemu-system-i386 nasm.out

, print an endless stream of characters to the screen !

:

bits 16
global main
main:
    mov ah, 0x0e
    mov al, '!'
    int 0x10
    jmp main
times 510 - ($ - $$) db 0x00
db 0x55
db 0xaa

      

I was curious if I could use Clang as my assembler instead of nasm, so I tried to translate the program into what I consider to be the syntactic equivalent of GAS:

.code16
.global main
main:
    mov $0x0e, %ah
    mov $'!', %al
    int $0x10
    jmp main
.fill 510 - (. - main)
.byte 0x55
.byte 0xaa

      

However, when compiling with, /usr/local/opt/llvm/bin/clang --target=i386-elf -m16 -c boot.s -o boot.o

I get the following error:

boot.s:9:7: error: expected absolute expression
.fill 510 - (. - main)
      ^

      

Compilation succeeds if jmp main

replaced with jmp *0x00

or the statement is not jmp

. This is not strictly equivalent, but seems to indicate something about the shortcut that gives the Clan problems.

nasm

had no problem figuring out the number of bytes to fill. Why doesn't Klang work when I ask him to do the same? Is there some subtle (or obvious) thing I missed?

I can always manually figure out how many padding bytes I need, but this is tedious and error prone, and seems like something assembler should do on its own.

I am running Clang 4.0 installed via Homebrew on macOS 10.12.6.


  • Fast bootloader to restart, if you need it: the boot sector has a length of 512 bytes and must have a value 0x55

    and 0xaa

    for displacements 510 and 511 respectively. An easy way to ensure that the binary output has a length of 512 bytes and has 0x55

    and 0xaa

    as the last two bytes.
+4


source to share


2 answers


It seems to be a bug in Apple's assembler. Although the assembler runs in one pass, the computation . - main

must be allowed to an absolute value.

You should be able to replace .fill

with a directive .org 510

to advance the location counter 510 bytes from the beginning of the current section. From the manual :

7.68 .org new-lc, fill

Move the current partition location counter to new-lc . new-lc is an absolute expression, or an expression with the same section as the current subsection. This, you cannot use .org for sections: if new-lc has an invalid section, the .org directive is ignored. Be compatible with legacy assemblers if the new-lc section is absolute because it issues a warning, then pretends that the new-lc section is the same as the current subkey.

[snip]

Remember that the source refers to the beginning of a section , not the beginning of a subsection. It is compatible with other peoples assemblers.



This should work:

.code16
.global main
main:
    mov $0x0e, %ah
    mov $'!', %al
    int $0x10
    jmp main
.org 510
.byte 0x55
.byte 0xaa

      

I was able to reproduce your problem with clang-900.0.39.2

and using it .org

worked with this version.

+1


source


Clang has its own assembler which does not understand all of the GNU assembler syntax. Try building with the GNU compiler, i.e. Using as --32 -o boot.o boot.s

then it should work.



0


source







All Articles