GNU Assembler(GAS)如何判断宏参数是否为寄存器
GAS宏判断参数是否为寄存器的正确实现
你原来的代码有两个核心问题:
- 参数名拼写错误:宏定义的形参是
myParameter,条件判断里写的是myParamater(少了字母e),会直接触发汇编报错。 - 判断逻辑完全无效:GAS默认宏模式不支持直接用
== "register"这种语法获取参数类型,这种写法不会得到你想要的判断结果。
正确实现方案
GAS提供了增强宏模式,开启后可以直接用内置的%isreg()函数判断参数是否为寄存器,不需要自己枚举寄存器名做字符串匹配,写法如下:
# 开启增强宏模式,启用内置类型判断函数 .altmacro .macro myMacro myParameter .if %isreg(\myParameter) // 参数为寄存器时执行的代码块 mov rax, 1 .else // 参数为非寄存器(立即数、内存引用等)时执行的代码块 mov rax, 2 .endif .endm # 不需要增强宏特性时可以切回默认模式,避免和其他宏逻辑冲突 .noaltmacro
调用效果验证
myMacro rdi # 识别为寄存器,汇编后生成 mov rax, 1 myMacro $2 # 识别为立即数,汇编后生成 mov rax, 2 myMacro [rbx] # 识别为内存操作数,汇编后生成 mov rax, 2
%isreg()会自动识别当前目标架构下所有合法寄存器,包括通用寄存器、向量寄存器、控制寄存器、调试寄存器,不需要手动维护寄存器列表。
老版本GAS兼容方案
如果你使用的GAS版本低于2.27,不支持%isreg()内置函数,可以通过枚举常用寄存器+字符串比较的方式实现判断,缺点是必须手动覆盖所有你可能传入的寄存器名,漏写就会出现判断错误:
.macro myMacro myParameter .is_reg = 0 # 枚举所有可能传入的寄存器 .irp reg,rax,rbx,rcx,rdx,rsi,rdi,rsp,rbp,r8,r9,r10,r11,r12,r13,r14,r15,eax,ebx,ecx,edx,esi,edi,esp,ebp,ax,bx,cx,dx,al,bl,cl,dl .ifc "\myParameter","\reg" .is_reg = 1 .exitm .endif .endr .if .is_reg mov rax, 1 .else mov rax, 2 .endif .endm
注意:x86/GNU汇编语法中立即数需要加
$前缀,直接写数字会被识别为内存地址,不属于合法立即数写法。
内容的提问来源于stack exchange,提问作者Citra Dewi
相关产品推荐
相关产品推荐

