'sp' 是什么意思?在 asm clobber 列表中是什么意思?

发布于 2024-12-01 03:53:08 字数 333 浏览 0 评论 0原文

我正在努力获取一些 x86 程序集以在 Core 2 Duo Mac 上进行编译。对于如下语句,使用 clang 会返回 无效操作数 错误:

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

其中 foobarlong。我想知道 sp 关键字在 clobber 列表中的含义是什么,因为 GCC / llvm 文档和 Google 都无法对它们提供太多说明。有人知道 clobber 关键字的完整列表吗?

I'm struggling to get some x86 assembly to compile on a Core 2 Duo Mac. Using clang returns an invalid operand error for statements like the following:

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

Where foobar is a long. I was wondering what the sp keyword means in the clobber list as neither the GCC / llvm doc nor Google can shed much light on them. Does anybody know of a comprehensive list of clobber keywords?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

歌枕肩 2024-12-08 03:53:08

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

为什么它是 sp 而不是 esp,我无法告诉你,但是,如果你遇到错误,这是我要更改的第一件事,看看这是否是问题。

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

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

Surely that would be the stack pointer, especially since you're actually subtracting something from the stack pointer esp. You probably already know this bit but, just in case, the cc is the condition code register (the flags and so forth).

Why it's sp and not esp, I couldn't tell you but, if you're getting errors, that's the first thing I'd change to see if that was the problem.

The values that you're supposed to be able to put in there are all the registers that may be clobbered (other than those explicitly listed for output which gcc already knows will change) and the special value memory if you don't want gcc to assume any cached memory values will remain valid.

The registers, of course, depend on the underlying architecture. Not sure that's a comprehensive list but it's all I've ever used, or needed to use.

睡美人的小仙女 2024-12-08 03:53:08

看着 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 逻辑,并且使您能够使用 clang 构建它。

== 更新==

gcc 也有可能存储 clobber 的寄存器访问大小。这是 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];

<一href="http://google.com/codesearch#qoCVjtE_vOw/gcc4/trunk/gcc-4.4.3/gcc/config/i386/i386.h&q=x 86%20%22%5C%22sp%5C%22%22&exact_package=http://mosync.googlecode.com/svn&type=cs&l=865" rel="nofollow">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 }

因此,在没有大小字段检查的情况下检查寄存器破坏冲突(对于非 mm/xmm 寄存器)。

Looking at gcc-4.4.3/gcc/config/i386/i386.h :2036 file I conclude that "sp" is gcc-specific alias of "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 } }

Both "sp" and "esp" (and "rsp" too) will code register number 7.

So, this code is legal for GCC; but is you want to make it portable (compilable by clang), change "sp" to "esp". This patch will not change gcc logic and will enable you to build this with clang.

== Update==

there is a possibility that gcc stores size of register access for clobbers too. Here is the the checker function of asm registers - 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);

The conflict (overlap) is checked via HARD_REG_SET, which has size 52 bits:

gcc/hard-reg-set.h :50. Hard_reg_set has length of FIRST_PSEUDO bits, rounded up to fill fastint fully.

#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 has a list of registers in the 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 }

So register-clobber conflict is checked without size field check (for non-mm/xmm regs).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文