了解C语言中的x86 ASM函数

时间:2018-09-27 16:17:45

标签: c assembly x86

我目前正在完成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](小写)的来源。我已经阅读了一些文档,但没有找到答案。希望有帮助!

谢谢

2 个答案:

答案 0 :(得分:2)

在GCC的扩展程序集语法中,表示法 [ name ]“ constraints ”(< / b> 表达式 说:

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

答案 1 :(得分:1)

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

GCC documentation中获取ASM模板:

[ [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