【问题标题】:"Junk after expression" using GNU Assembler macro使用 GNU 汇编器宏的“表达式后的垃圾”
【发布时间】:2026-01-29 03:00:02
【问题描述】:

我大致关注this guide 设置一个简单的操作系统。它提供了一些用于 NASM 的程序集,但我使用的是 GNU Assembler。

在我正在使用的程序集文件的顶部

.intel_syntax noprefix

我已经定义了一个这样的宏

.macro no_error_code_handler num
.global interrupt_handler_\num
.type interrupt_handler_\num, @function
interrupt_handler_\num:
    push dword 0
    push dword \num
    jmp common_int_handler
.endm

如果重要,common_int_handler 在附近定义为

common_int_handler:
    pushad
    call int_handler # This is a C function
    popad
    add esp, 8
    iret

最后我有一行

no_error_code_handler 0

我希望扩展到类似的东西

.global interrupt_handler_0
.type interrupt_handler_0, @function
interrupt_handler_0:
    push dword 0
    push dword 0
    jmp common_int_handler

编译时,no_error_code_handler 0 行出现错误提示

Assembler messages:
Error: junk `0' after expression
Error: junk `0' after expression

它是否与将类型定义为函数有关,即使它的行为不像普通函数?我应该在iret 指令之后离开后在某处使用.exitm 吗?

【问题讨论】:

  • 为了效率,您只需要保存/恢复调用破坏的寄存器。编译器生成的函数已经将调用保留的 regs 保留为调用约定的一部分。
  • 在调用 C 代码(函数 int_handler)之前,中断代码也缺少 CLD 指令。您必须确保为字符串指令设置了方向标志。如果被中断的代码恰好发出了 STD 指令,并且中断代码使用了 x86 字符串指令,那么代码中断可能无法按预期工作。

标签: assembly macros x86 preprocessor gnu-assembler


【解决方案1】:

以下几行导致错误

push dword 0
push dword \num

dword 在此上下文中无效。

push 0
push \num

删除 dword 解决了问题

【讨论】:

  • 不是因为你指定了.intel_syntax noprefix。那也不是有效的 AT&T 语法。 GAS 的 intel_syntax 模式不像 NASM;它更像是 MASM。