PAYATHON 2026

GNU as 中添加跳转指令后 .rept 报绝对表达式错误怎么办?

数据小许

结论

报错来自 .rept 的重复次数表达式。GNU as 要求重复次数在汇编时是确定的绝对常量。jmp 或 je 的编码长度可能需要调整;如果前面的指令长度尚未确定,510 - (. - _start) 就无法作为 .rept 的绝对重复次数。

原始代码显示,添加 je _exit 或取消注释 #jmp _loop 后,错误会指向这一行:

.rept 510 - (. - _start)

原始粘贴内容在 mov 和 cmp 附近夹有汇编器版本和命令行信息,因此无法确认完整的指令序列。下面的处理方式适用于 _start 位于目标 section 起始处,且代码与数据总长度不超过 510 字节的情况。

推荐做法:用 .org 填充到偏移 510

.section .text
.code16
_start:
    # boot sector code goes here

.org 510, 0
.byte 0x55, 0xaa

.org 510, 0 会将当前位置推进到当前 section 的偏移 510,并用 0 填充空隙。随后写入的两个字节 0x55, 0xaa 会使 boot sector 总长达到 512 字节。如果代码已经超过偏移 510,汇编会失败,需要先缩短代码或数据。

如果文件还包含其他内容,或 _start 不是该 section 的起点,应先确认 section 布局。这里的 .org 510 是从当前 section 的起始位置计算偏移。

若要继续使用 .rept

重复次数必须能在汇编时计算为绝对常量。可以检查跳转指令是否因目标距离需要较长编码,以及 .rept 之前是否还有长度尚未确定的指令。若 GAS 语法支持显式短跳转写法,也可以在确认目标距离处于短跳转范围内后指定短编码。具体写法取决于指令模式和汇编器语法。

此外,bootloader 通常需要明确设置 .code16。原始命令是在 x86_64 主机上运行 as,但主机架构不会自动让源文件进入 16 位代码模式。这个设置与 .rept 的绝对表达式报错是两个独立问题。

注意事项

汇编完成后,应检查输出 section 的大小以及末尾签名的位置。若使用链接器生成最终镜像,还需确认链接脚本没有改变代码相对于 boot sector 起点的布局。

备注:内容仅供参考。