我正在努力获得一些x86汇编在Core 2 Duo Mac上编译。使用clang返回invalid operand
错误,如以下语句:
asm volatile ("subl %0,%%esp" :: "r"(foobar) : "cc", "sp");
其中foobar
为long
。我想知道sp
关键字在clober列表中意味着什么,因为GCC/llvm文档和谷歌都不能对它们透露太多信息。有人知道一个完整的关键词列表吗?
肯定是堆栈指针,特别是,因为您实际上从堆栈指针esp
中减去了一些东西。您可能已经知道这一点,但是,以防万一,cc
是条件代码寄存器(标志等)。
为什么是sp
而不是esp
,我不能告诉你,但是,如果你得到错误,这是我要改变的第一件事,看看这是不是问题。
你应该能够放在那里的值是所有可能被破坏的寄存器(除了那些显式列出的输出,gcc
已经知道会改变)和特殊值memory
,如果你不希望gcc
假设任何缓存的内存值将保持有效。
查看gcc-4.4.3/gcc/config/i386/i386.h:2036文件,我得出结论,"sp"是"esp"的gcc特定别名:
/* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number (see above). */
/* In order to refer to the first 8 regs as 32-bit regs, prefix an "e".
For non floating point regs, the following are the HImode names.
For float regs, the stack top is sometimes referred to as "%st(0)"
instead of just "%st". PRINT_OPERAND handles this with the "y" code. */
#define HI_REGISTER_NAMES
{"ax","dx","cx","bx","si","di","bp","sp",
"st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)",
"argp", "flags", "fpsr", "fpcr", "frame",
"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7",
"mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"}
#define REGISTER_NAMES HI_REGISTER_NAMES
/* Table of additional register names to use in user input. */
#define ADDITIONAL_REGISTER_NAMES
{ { "eax", 0 }, { "edx", 1 }, { "ecx", 2 }, { "ebx", 3 },
{ "esi", 4 }, { "edi", 5 }, { "ebp", 6 }, { "esp", 7 },
{ "rax", 0 }, { "rdx", 1 }, { "rcx", 2 }, { "rbx", 3 },
{ "rsi", 4 }, { "rdi", 5 }, { "rbp", 6 }, { "rsp", 7 },
{ "al", 0 }, { "dl", 1 }, { "cl", 2 }, { "bl", 3 },
{ "ah", 0 }, { "dh", 1 }, { "ch", 2 }, { "bh", 3 } }
"sp"one_answers"esp"(以及"rsp")都将对编号为7的寄存器进行编码。
所以,这段代码在GCC中是合法的;但是如果你想让它可移植(通过clang编译),把"sp"改成"esp"。这个补丁不会改变gcc的逻辑,并且可以让你用clang来构建它。
= = = =
更新有可能GCC也为clobbers存储寄存器访问的大小。下面是asm寄存器的检查器函数- clobbers冲突(gcc/stmt.c):
tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
{
/* Conflicts between asm-declared register variables and the clobber
list are not allowed. */
tree overlap = tree_overlaps_hard_reg_set (t, clobbered_regs);
冲突(重叠)通过HARD_REG_SET检查,大小为52位:
gcc/hard-reg-set.h: 50。Hard_reg_set的长度为FIRST_PSEUDO位,四舍五入以完全填充fastint。
#define HARD_REG_SET_LONGS
((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_WIDEST_FAST_INT - 1)
/ HOST_BITS_PER_WIDEST_FAST_INT)
typedef HARD_REG_ELT_TYPE HARD_REG_SET[HARD_REG_SET_LONGS];
i386/i386.h:865: #define FIRST_PSEUDO_REGISTER 53
:882同一个文件在HARD_REG_SET:
中有一个寄存器列表#define FIXED_REGISTERS
/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
/*arg,flags,fpsr,fpcr,frame*/
1, 1, 1, 1, 1,
/*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/
0, 0, 0, 0, 0, 0, 0, 0,
/* mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7*/
0, 0, 0, 0, 0, 0, 0, 0,
/* r8, r9, r10, r11, r12, r13, r14, r15*/
2, 2, 2, 2, 2, 2, 2, 2,
/*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/
2, 2, 2, 2, 2, 2, 2, 2 }
所以register- clober冲突检查没有大小字段检查(对于非mm/xmm regs)。