I'm messing around with writing a simple toy boot loader (additional info at bottom of post). The following nasm code shows what the bootloader looked like at one point before I tried to switch to Clang. When compiled using nasm -f bin -o nasm.out boot.asm, then run using qemu-system-i386 nasm.out, prints 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 translating the program to what I think is the GAS syntax equivalent:
.code16
.global main
main:
mov $0x0e, %ah
mov $'!', %al
int $0x10
jmp main
.fill 510 - (. - main)
.byte 0x55
.byte 0xaa
However, when compiled using /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 is replaced with jmp *0x00 or a non-jmp instruction. It's not strictly equivalent, but it seems to point towards something about the label which is giving Clang issues.
nasm didn't have any issues figuring out how many bytes to use for padding. Why does Clang balk when I ask it to do the same? Is there some subtle (or obvious) thing which I missed?
I can always manually figure out how many bytes of padding I need, but that's tedious and error-prone, and seems like something the assembler should be able to do on its own.
I'm running Clang 4.0, installed through Homebrew, on macOS 10.12.6.
- Quick bootloader refresher, if you need it: the boot sector is 512 bytes long, and needs to have the values
0x55and0xaaat offsets 510 and 511, respectively. The easy way of ensuring this is to make sure the binary output is exactly 512 bytes long, and has0x55and0xaaas its last two bytes.