【问题标题】:Understanding an x86 ASM function in C了解 C 中的 x86 ASM 函数
【发布时间】:2018-09-27 16:17:45
【问题描述】:

我目前正在处理 pintos 项目,并且对项目包含的一些汇编宏有疑问

#define syscall1(NUMBER, ARG0)                                           \
({                                                               \
  int retval;                                                    \
  asm volatile                                                   \
    ("pushl %[arg0]; pushl %[number]; int $0x30; addl $8, %%esp" \
       : "=a" (retval)                                           \
       : [number] "i" (NUMBER),                                  \
         [arg0] "g" (ARG0)                                       \
       : "memory");                                              \
  retval;                                                        \
})

调用这个宏来为只有一个参数的系统调用设置堆栈。我们将一个参数,系统调用号和陷阱推送到内核。我们只传递了 NUMBER 和 ARG0,我想知道 [number] 和 [arg0](小写)从何而来。我已经阅读了一些文档,但没有找到答案。希望得到一些帮助!

谢谢

【问题讨论】:

  • 文档是here。您可以在以 "The following i386 example uses the asmSymbolicName syntax" 开头的段落之后找到类似的语法
  • [arg0] 和 [number] 只是程序员给出的用户定义名称(它们是别名)。相同的名称用于替换扩展程序集本身。名称可以是您选择的任何标识符。如果没有它们,扩展的内联程序集将显示为 "pushl %1; pushl %0; int $0x30; addl $8, %%esp 。而不是使用像 %0 和 %1 这样的位置值,这些名称使代码更具可读性和可维护性。

标签: c assembly x86


【解决方案1】:

在 GCC 的扩展汇编语法中,表示法 [name] "constraints" (表达式) 说:

  • 使表达式可用于汇编代码。
  • 将表达式放在满足约束的位置。 约束描述了可接受的使用位置,例如通用处理器寄存器、浮点寄存器和内存。它们还可能包括告诉 GCC 表达式将被汇编代码更改或读取和更改的符号。 (对于输出操作数,表达式应该是一个左值,以便为要写入的新值提供一个位置。)
  • 使用 name 作为地点的名称。然后,当 GCC 在汇编代码中看到 %[name] 时,它会将其替换为引用该地点的汇编表达式,例如%rax 或 16(r3)。操作数表示法的 [name] 部分是可选的。如果你不给它,GCC 会给出操作数名称 0, 1, 2,…,所以汇编代码会用 %0, %1 来引用它们, %2,...

【讨论】:

    【解决方案2】:

    方括号中的部分是仅在 ASM 模板中使用的符号名称。括号中的部分是对 C 程序中变量名的引用。 (下面有更详细的描述)

    来自 ASM 模板的 GCC documentation:

    [ [asmSymbolicName] ] constraint (cvariablename)
    
    • asmSymbolicName

      指定操作数的符号名称。通过将其括在方括号中来引用汇编程序模板中的名称(即“%[Value]”)。名称的范围是包含定义的 asm 语句。* 任何有效的 C 变量名称都是可接受的,包括已在周围代码中定义的名称。 *不能有两个操作数在同一个 asm 语句中可以使用相同的符号名。

      当不使用asmSymbolicName 时,使用汇编器模板中操作数列表中操作数的(从零开始的)位置。例如,如果有三个输出操作数,则在模板中使用“%0”来引用第一个,“%1”代表第二个,“%2”代表第三个。

    • 约束

      一个字符串常量,指定操作数放置的约束;有关详细信息,请参阅约束。
      输出约束必须以“=”(覆盖现有值的变量)或“+”(读取和写入时)开头。使用‘=’时,不要假设该位置包含 asm 条目上的现有值,除非操作数与输入相关联;请参阅输入操作数。

      在前缀之后,必须有一个或多个附加约束(请参阅约束)来描述值所在的位置。常见的约束包括寄存器的“r”和内存的“m”。当您列出多个可能的位置(例如,“=rm”)时,编译器会根据当前上下文选择最有效的位置。如果在 asm 语句允许的范围内列出尽可能多的替代项,则允许优化器生成可能的最佳代码。如果您必须使用特定寄存器,但您的机器约束没有提供足够的控制来选择您想要的特定寄存器,则本地寄存器变量可能会提供解决方案(请参阅本地寄存器变量)。

    • 变量名

      指定一个 C 左值表达式来保存输出,通常是一个变量名。括号是语法的必需部分。*

    ...

    Extended Asm - Assembler Instructions with C Expression Operands

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      相关资源
      最近更新 更多