我正在使用一个库(pulseaudio、src/pulsecore/svolume_mmx.c),它的代码类似于以下虚拟代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
int main(int argc, char *argv[]) {
int32_t x = 5;
int32_t *p_x = &x;
#if defined(__i386__)
int32_t tmp;
#elif defined(__amd64__)
int64_t tmp;
#endif
__asm__ __volatile__ (
" xor %1, %1 \n\t"
" movd (%q0, %1, 4), %%mm0 \n\t"
" emms \n\t"
: "+r" (p_x), "+r" (tmp)
);
printf("%"PRId32"\n", x);
return 0;
}
我正在尝试将其编译为 64 位 mac osx 上的 32 位库。当我正常编译它时,一切正常,但是当我使用 -arch 标志将它编译为所需的 32 位库时,会发生这种情况:
$ gcc -std=c99 -arch i386 -o main main.c
/var/folders/random_stuff_here.s:22:bad register name `%rcx, %edx,4)'
读取 gcc 的汇编输出后,问题出在 movd 行。%q0 寄存器被填充为 %rcx,它是一个 64 位寄存器。汇编器试图从中创建 32 位输出,但失败了。
我找不到太多关于 %q0 中的 'q' 的含义,但我最终找到了不同编译器的文档(第 194 页),它将 q 描述为“如果目标为操作数,则为操作数生成四字寄存器名称支持四字。否则,它会产生一个字寄存器名称。(例如,如果操作数 0 在寄存器 'a' 中,则 %q0 在 x86_64 上产生 %rax 或在 x86 上产生 %eax。)如果您使用 'q' 标志请求 asm 块输出 64 位寄存器,即使 -arch 标志指定 32 位输出也是如此。
除了 -arch i386 标志之外,使用 -m32 标志根本没有帮助。如何告诉 asm 代码生成器仅对 %qx 符号使用 32 位寄存器?我宁愿为 gcc 提供额外的标志,而不是修改这个库的源代码。