【发布时间】:2019-07-22 09:36:51
【问题描述】:
我试图了解这段内联汇编的作用,它是从 C DEFINE 宏生成的:
#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
它被用于在 linux-imx 内核分支中执行 AArch64 smc 调用的一些魔法。以上C宏定义值的地方是here:
// arch/arm64/kernel/asm-offsets.c
int main(void)
{
(...)
DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
(...)
}
后来,这些定义用于汇编宏available here(或者至少看起来是这样):
// arch/arm64/kernel/smccc-call.S
.macro SMCCC instr
.cfi_startproc
\instr #0
ldr x4, [sp]
stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS]
stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS]
ldr x4, [sp, #8]
cbz x4, 1f /* no quirk structure */
ldr x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS]
cmp x9, #ARM_SMCCC_QUIRK_QCOM_A6
b.ne 1f
str x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS]
1: ret
.cfi_endproc
.endm
ENTRY(__arm_smccc_smc)
SMCCC smc
ENDPROC(__arm_smccc_smc)
最终在实践中使用,例如在gpc-psci driver。
我试图将代码隔离到一个单独的裸机 AArch64 程序中,以查看宏在实践中是如何扩展和工作的,但我得到的只是编译错误。
// main.c
// the struct arm_smccc_res and others are inserted here to satisfy the compiler
int
main()
{
DEFINE(ARM_SMCCC_RES_X0_OFFS, offsetof(struct arm_smccc_res, a0));
DEFINE(ARM_SMCCC_RES_X2_OFFS, offsetof(struct arm_smccc_res, a2));
DEFINE(ARM_SMCCC_QUIRK_ID_OFFS, offsetof(struct arm_smccc_quirk, id));
DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS, offsetof(struct arm_smccc_quirk, state));
return 0;
}
// gcc output
/tmp/cccqaaY3.s: Assembler messages:
/tmp/cccqaaY3.s:459: Error: junk at end of line, first unrecognized character is `-'
/tmp/cccqaaY3.s:464: Error: junk at end of line, first unrecognized character is `-'
/tmp/cccqaaY3.s:469: Error: junk at end of line, first unrecognized character is `-'
/tmp/cccqaaY3.s:474: Error: junk at end of line, first unrecognized character is `-'
offsetof 宏是不言自明的,但我无法理解在DEFINE 宏中使用字符串化和->。
有什么想法可以扩展成什么,或者如何成功编译它?
【问题讨论】:
-
[macro] 标签是这些标签中最不重要的...不能适合内联汇编
-
在源文件上使用
gcc -S为该文件生成程序集。大概DEFINEs 只在程序集文件的中间才有意义——这就是asm volatile的作用,以确保它们不会被移动......
标签: c gcc assembly gnu-assembler arm64