2011-08-25 92 views
3

我努力让一些x86程序集在Core 2 Duo Mac上编译。使用铛返回invalid operand错误,如下面的语句:'sp'在asm clobber列表中是什么意思?

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

foobarlong。我想知道sp关键字在clobber列表中意味着什么,因为GCC/llvm文档和Google都不能说明它们。有人知道clobber关键字的全面列表吗?

+0

“clobber关键字”是寄存器名称。也许而不是''sp'''你想指定'“esp”'。 –

+0

我意识到你可以明确地指定寄存器,但[文档](http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3)表示GAS还支持关键字“内存“和”cc“。虽然没有关于“sp”的文字。 –

回答

1

看着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” 和 “ESP”(和 “RSP” 太)将代码寄存器号7.

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

== ==更新

有一种可能性,即对寄存器访问GCC门店规模则会覆盖了。下面是ASM寄存器方格功能 - 则会覆盖冲突(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 } 

所以寄存器撞冲突而不大小字段校验检查(对于非毫米/ XMM暂存器)。

+0

好的电话,从来没有想过要看那里。我有一些其他问题与我的'端口',但内联程序集仍在编译。 –

4

当然,这将是堆栈指针,特别是,因为你实际上是从堆栈指针esp减去一些东西。你可能已经知道这一点,但是,以防万一,cc是条件代码寄存器(标志等)。

为什么它是sp而不是esp,我不能告诉你,但是,如果你得到错误,那我会改变的第一件事,看看是否是这个问题。

您应该可以在其中放置的值是所有可能被破坏的寄存器(除了那些明确列出的输出已知的将会更改的寄存器)以及特殊值memory如果您不' t想要gcc假设任何缓存的内存值将保持有效。

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

+0

这正是我所看到的,直到我阅读相当不成文的例子。该代码适用于x86 linux,我想知道是否与Darwin堆栈对齐有关。我有点惊讶,虽然没有所有这些关键字的GCC参考... –

+2

sp是x86上的寄存器;这是esp的最低16位。 – servn

+0

@servn,我明白了,但是这条指令可能会改变'esp'的_all_,而不仅仅是低位。这就是为什么我质疑它是否应该'esp'。 – paxdiablo