awk*_*ksp 6 macos x86 assembly clang bootloader
我正在编写一个简单的玩具引导加载程序(帖子底部的附加信息)。以下nasm代码显示了在我尝试切换到 Clang 之前的某个时刻引导加载程序的样子。当编译 using nasm -f bin -o nasm.out boot.asm,然后运行 using 时qemu-system-i386 nasm.out,!会在屏幕上打印出无穷无尽的字符流:
bits 16
global main
main:
mov ah, 0x0e
mov al, '!'
int 0x10
jmp main
times 510 - ($ - $$) db 0x00
db 0x55
db 0xaa
Run Code Online (Sandbox Code Playgroud)
我很好奇我是否可以使用 Clang 作为我的汇编程序而不是 nasm,所以我尝试将程序翻译成我认为与 GAS 语法等效的内容:
.code16
.global main
main:
mov $0x0e, %ah
mov $'!', %al
int $0x10
jmp main
.fill 510 - (. - main)
.byte 0x55
.byte 0xaa
Run Code Online (Sandbox Code Playgroud)
但是,当使用编译时/usr/local/opt/llvm/bin/clang --target=i386-elf -m16 -c boot.s -o boot.o,我收到以下错误:
boot.s:9:7: error: expected absolute expression
.fill 510 - (. - main)
^
Run Code Online (Sandbox Code Playgroud)
如果jmp main替换为jmp *0x00或 非jmp指令,则编译成功。它不是严格等效的,但它似乎指向了一些给 Clang 问题的标签。
nasm确定用于填充的字节数没有任何问题。为什么 Clang 在我要求它做同样的事情时犹豫不决?我错过了一些微妙(或明显)的东西吗?
我总是可以手动计算出我需要多少字节的填充,但这既乏味又容易出错,而且似乎汇编程序应该能够自行完成。
我正在 macOS 10.12.6 上运行通过 Homebrew 安装的 Clang 4.0。
0x55和0xaa。确保这一点的简单方法是确保二进制输出的长度恰好为 512 字节,并且将0x55和0xaa作为其最后两个字节。这似乎是苹果汇编程序中的一个错误。虽然汇编程序是单遍,但计算. - main应该可以解析为绝对值。
您应该能够将 替换.fill为.org 510指令,将位置计数器从当前节的开头前进 510 个字节。来自手册中:
\n\n\n7.68 .org new-lc , 填充
\n\n将当前节的位置计数器前进到 new-lc。new-lc 是绝对表达式或与当前子节具有相同节的\n 表达式。也就是说,\n 您可以\xe2\x80\x99t 使用 .org 来交叉部分:如果 new-lc 有错误的部分,\n .org 指令将被忽略。为了与以前的汇编器兼容,如果 new-lc 的部分是绝对的,则发出警告,然后假装 new-lc 的部分与当前子部分相同。
\n\n[剪]
\n\n请注意,原点是相对于该节的开头,而不是相对于该小节的开头。这与其他人\xe2\x80\x99s\n 汇编器兼容。
\n
这应该有效:
\n\n.code16\n.global main\nmain:\n mov $0x0e, %ah\n mov $\'!\', %al\n int $0x10\n jmp main\n.org 510\n.byte 0x55\n.byte 0xaa\nRun Code Online (Sandbox Code Playgroud)\n\n我能够重现您的问题clang-900.0.39.2,并使用.org该版本的工作。