受最近的一个问题的启发。
使用gcc风格的内嵌汇编的一个用例是编码编译器和汇编器都不知道的指令。例如,我提供了这个示例,演示如何在支持不了rdrand指令的旧工具链上使用该指令。
/* "rdrand %%rax ; setc %b1" */
asm volatile (".byte 0x48, 0x0f, 0xc7, 0xf0; setc %b1"
: "=a"(result), "=qm"(success) :: "cc");
不幸的是,硬编码指令意味着您还需要硬编码与之一起使用的寄存器,这大大降低了编译器执行寄存器分配的自由度。
在某些体系结构上(例如具有.insn
指令的 RISC-V),汇编器提供了一种系统化构建原始指令的方式,但这似乎是个例外。
一个简单的解决方案是找到一种方法来获取未装饰的寄存器编号,并将其手动编码到指令中。例如,假设存在模板修饰符 X
以打印所选择的寄存器的编号。那么,上面的示例可以更加灵活地改写:
/* "rdrand %0 ; setc %b1" */
asm volatile (".byte 0x48 | (%X0 >> 3), 0x0f, 0xc7, 0xf0 | (%X0 & 7); setc %b1"
: "=r"(result), "=qm"(success) :: "cc");
类似地,如果有一种方法可以让gcc在ARM64上将SIMD寄存器12打印为
12
而不是v12
,那么就可以执行以下操作:float32x4_t add3(float32x4_t a, float32x4_t b)
{
float32x4_t c;
/* fadd %0, %1, %2 */
asm (".inst 0x4e20d40 + %X0 + (%X1<<5) + (%X2<<16)" : "=w"(c) : "w"(a), "w"(b));
return c;
}
有没有一种方法可以获得寄存器编号?如果没有,是否存在其他选项来编码指令,既不需要编译器也不需要汇编器知道,而又不必硬编码寄存器编号?
%rax
会破坏一些东西... - Siguza%X0
与.L__reg_const__
直接拼接,他正在创建一个以寄存器名称作为符号名称后缀的标识符。在标识符中使用百分号可能会对x86产生问题,但我相信有一个修改器 (V
)可以关闭它。 - David Wohlferd