【问题标题】:GCC extended asm, struct element offset encodingGCC 扩展 asm,struct 元素偏移编码
【发布时间】:2012-10-26 14:40:19
【问题描述】:

我正在尝试以 GCC 样式扩展 asm(x86-64 目标)编写一小段代码,但在编码结构偏移时遇到了问题。

我有一个 struct s 和一个成员 size_t a[]、一个指向此类结构的指针和一个索引,这两者都是在 asm 块中生成的。

现在我需要在 asm 中处理该元素

asm (
    "mov %[displ](%[s], %[index], 8), %%rbx"
    : [s] "+r" (s)
    , [index] "+r" (i)
    : "memory", "cc", "rax", "rbx"
);

如何将displ 编码到 asm 块中?将offsetof(struct s, a) 作为立即数传递给它加上$ 前缀并生成无效程序集。

asm (
    "mov %[displ](%[s], %[index], 8), %%rbx"
    : [s] "+r" (s)
    , [index] "+r" (i)
    : [displ] "i" (offsetof(struct s, a))
    : "memory", "cc", "rax", "rbx"
);

【问题讨论】:

  • 为什么? C代码中s.a[index]有什么问题?
  • 因为上面是一个较小的例子,实际上 asm 块很大,包含更多的指令和几个跳转。因为这不是我第一次需要这种效果。
  • 好的,如果它是一个大块的程序集,我会考虑将它放在一个单独的 .asm 文件中,让 C 代码计算并传递所需的参数。您无法在汇编中更有效地计算地址,所以对我来说,这似乎是我们可以避免的复杂情况。
  • 嗯,结构体在 C 和 asm 代码中都使用,所以我需要在两者之间有相同的偏移量。

标签: c gcc inline-assembly i386


【解决方案1】:

实际上可能的,使用%c...操作数修饰符:

#include <stddef.h>
#include <stdint.h>

struct s
{
  int a, b;
};

int foo (struct s *s, int i)
{
  int r;
  asm (
       "movl %c[displ](%[s],%[index],8), %[r]\n\t"
       : [r] "=r" (r)
       : [s] "r" (s) , [index] "r" ((uintptr_t)i),
         [displ] "e" (offsetof(struct s, b))
       :
       );

  return r;
}

感谢该感谢的地方 - 发现 herea gcc mailing list posting 也提到了这个;那里的关键字是“输出替换”。
stackoverflow 的帖子What does %c mean in GCC inline assembly code? 也有关于%c 的解释。

【讨论】:

    【解决方案2】:

    您唯一的选择是使用 Intel 语法。当然,GCC 可以生成像 mov off(base, index, scale) 这样的 insn,但这是在整个 MEM RTL 表达式的级别上执行的,即没有像单个操作数那样的偏移量、基数等。

    所以,英特尔语法,用gcc -c -masm=intel x.c 编译以下内容:

    #include <stddef.h>
    
    struct s
    {
      int a, b;
    };
    
    int foo (struct s *s, int i)
    {
      int r;
      asm (
           "mov %[r], dword ptr [%[s]+%[index]*8 + %[displ]] "
           : [r] "=r" (r)
           : [s] "r" (s) , [index] "r" (i),
             [displ] "e" (offsetof(struct s, b))
           :
           );
    
      return r;
    }
    

    【讨论】:

    • 我知道这一点,但它使我的代码与我在同一个文件中包含的某些设备驱动程序(具有 AT&T 样式的内联 asm)不兼容。是的,我知道我可以拆分它们,从而失去优化代码的意义。
    • 您可以使用.intel_syntax.att_syntax在语法类型之间来回切换。
    猜你喜欢
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多