【发布时间】:2015-03-28 19:28:06
【问题描述】:
我正在尝试将一些现有的内联 x86_64 程序集转换为 AArch64 兼容版本。我在编译时遇到以下错误:
/tmp/ccSvqF1I.s:72547: Error: operand 1 should be an integer register -- `str [0x4,x1],#0x43e00000'
/tmp/ccSvqF1I.s:72548: Error: operand 1 should be an integer register -- `str [20,x1],2'
下面的 x86_64 代码如果是原始代码和 AARch64 代码是我移植它的尝试。
x86_64 组装:
__asm__(
"incq (%0)\n\t"
"jno 0f\n\t"
"movl $0x0, (%0)\n\t"
"movl $0x43e00000, 0x4(%0)\n\t"
"movb %1, %c2(%0)\n"
"0:"
:
: "r"(&op1->value),
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "cc");
AArch64 组装
__asm__(
"add %0, %0, #1\n\t"
"bvc 0f\n\t"
"mov %0, #0x0\n\t"
"str [0x4, %0], #0x43e00000\n\t"
"str [%c2, %0], %1\n\t"
"0:"
:
: "r"(&op1->value),
"n"(IS_DOUBLE),
"n"(ZVAL_OFFSETOF_TYPE)
: "cc");
编辑:更新了新的尝试和错误消息
【问题讨论】:
-
听起来并不粗鲁,但您可能应该尝试使用 AArch64 指令和语法,而不是这样。
-
@Notlikethat 我猜我真正的问题是不理解 x86 代码的
%c2(%0)部分。我似乎找不到任何描述该代码作用的文档。 -
我的 x86 程序集相当生疏,我的知识是 Intel 语法,而不是 GNU 愚蠢的 AT&T 语法,但我认为这只是基址寄存器 + 立即偏移寻址,具有
ZVAL_OFFSETOF_TYPE的约束必须是编译时常量 - 请参阅 "x86 Operand Modifiers" in the docs。无论哪种方式,任何内存操作数都不适合 ARMmov指令。 -
@Notlikethat 所以装配线将
%1中的值移动到%c2中,偏移%0的值?对于 ARM 中的内存操作,mov指令的替代方案是什么?我查看了str,但这似乎只是将一个寄存器+偏移量移动到一个寄存器中,这与 x86 代码的作用相反。我已经用我的新尝试和相应的错误消息更新了代码。 -
x64 和 ARM64 的功能和语法有很大不同。为什么不让编译器为某些 C 代码生成汇编语言列表,以查看它对 ARM64 的期望。 ARM 是一种加载/存储架构,您不能将立即值存储到内存中。指令只能将寄存器移动到内存或内存到寄存器。