'sp'在asm clobber列表中的含义是什么?

时间:2011-08-25 12:42:51

标签: assembly llvm clang

我正在努力让一些x86程序集在Core 2 Duo Mac上进行编译。使用clang会为以下语句返回invalid operand错误:

asm volatile ("subl %0,%%esp" :: "r"(foobar) : "cc", "sp");

foobarlong的位置。我想知道sp关键字在clobber列表中意味着什么,因为GCC / llvm doc和Google都没有对它们有所了解。有人知道一个完整的clobber关键词列表吗?

2 个答案:

答案 0 :(得分:4)

肯定会是堆栈指针,尤其是,因为你实际上是从堆栈指针esp中减去了一些东西。您可能已经知道了这一点,但是,以防万一,cc是条件代码寄存器(标志等)。

为什么它是sp而不是esp,我无法告诉你,但是,如果你遇到错误,那就是我要改变的第一件事,看看这是不是问题。< / p>

你应该放在那里的值是所有可能被破坏的寄存器(除了为gcc已经知道的输出明确列出的那些将会改变的那些)和特殊值{{ 1}}如果您不希望memory假设任何缓存的内存值仍然有效。

寄存器当然取决于底层架构。不确定这是一个全面的列表,但它是我曾经使用或需要使用的所有内容。

答案 1 :(得分:1)

查看gcc-4.4.3/gcc/config/i386/i386.h :2036文件我得出结论,“sp”是特定于gcc的“esp”别名:

/* 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”和“esp”(以及“rsp”)都将代码寄存器编号为7。

因此,此代码对于GCC是合法的;但是你想让它变得便携(可以通过clang编译),将“sp”改为“esp”。这个补丁不会改变gcc逻辑,并且可以让你用clang构建它。

==更新==

gcc也有可能存储clobbers的寄存器访问大小。这是asm寄存器的检查函数 - clobbers conflict(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 same file在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-clobber冲突(对于非mm / xmm regs)。