【问题标题】:GCC Inline Assembly to BinaryGCC 内联汇编到二进制
【发布时间】:2017-01-31 04:19:12
【问题描述】:

在 C 或 C++ 中,您可以通过执行以下操作来实现内联汇编指令:

asm("assembly code");  

__asm__ ("assembly code");  

例子:

asm("movl %ebx, %eax"); /* moves the contents of ebx register to eax */
__asm__("movb %ch, (%ebx)"); /* moves the byte from ch to the memory pointed by ebx */

然后您可以生成交互以在您的汇编代码和您的 C/C++ 变量之间交换值:更多关于 here

我的问题是:编译器是否将每条内联汇编指令直接翻译成二进制对应的指令?或者这只是一种“模拟”?这就是说,我想知道您是否真的在访问处理器的寄存器,或者代码中处理的所有数据都存储在堆栈中,模拟汇编指令。对不起,如果这个问题很愚蠢。

【问题讨论】:

  • GCC 的内联汇编器执行简单的替换(如果使用扩展的汇编器模板),但将指令在单个 ASM 语句中按原样输出到代码中。所以是的,一旦编译成代码,它将使用真正的寄存器。这当然是假设程序没有在模拟器中运行。
  • 谢谢,只是有疑问

标签: gcc assembly compilation


【解决方案1】:

当您使用 '__asm__''asm' 关键字时,GCC/G++ 会将字符串解析为汇编指令。如果您使用'扩展程序集',即在字符串后包含冒号,以使变量与寄存器的'输入/输出'交互,内联汇编器做简单的替换,就像下面的例子:


__asm__ ("\
添加 %ebx,%eax;\
mov %ebx,%ecx;\
" : "=c"(output_variable) : "b"(first_operand),"a"(second_operand) : /*这里不需要*/);

注意每条装配线末尾的反斜杠。它是为了避免换行,以便使用一对引号来包含所有的汇编代码。另外,为了帮助内联汇编解析器,每条汇编指令必须以分号结尾


在双引号之间的指令/s之后,您可以添加三个冒号,在前两个之间,您声明将要接收输出的变量。注意"=c"(output_variable)的意思是ecx寄存器最后存储的值,会被转发到()之间的变量强>。

在最后两个冒号之间,您声明将用作输入的变量/值,因此在代码开头,括号之间的值分配给用引号之间的字母表示的寄存器(使用逗号用于多个输入)。

在最后一个冒号之后,是一个被破坏的寄存器列表。但是,在这种特殊情况下,这是可选的且无用的。更多关于整个 GCC 内联汇编 here.

所以,总而言之,执行是这样的:

  • 将输入值(如果有)替换到相应的寄存器中
  • 从汇编翻译成二进制
  • 将输出加载到分配的变量中,如果有的话

所以简短的回答是,一旦代码被编译成机器语言,转换将是一对一的,就像一个普通的汇编程序一样,因此它将使用真正的寄存器.


【讨论】:

  • 我忘了说,每条流水线末尾的反斜杠,是为了逃避行跳转,以便使用一对引号。而且,每条汇编指令都必须以分号结尾,以为这只是为了帮助内联汇编解析器
  • 还应该指出,您的示例将 ebx 添加到 eax 并将结果存储在 eax 中。您将 ebx 移动到 ecx,这实际上将 ebx 设置为 first_operand 的内容,而不是添加的值。
  • 每行不需要分号。 \n 换行符就可以了。最好是\n\t,如果您使用带有-S 选项的GCC 来输出由GCC 生成的汇编代码,它的格式会更好。您可以避免换行符如果您单独引用每一行。您的代码中的一个错误是扩展内联汇编器寄存器名称需要%% 而不是%。这也可以:__asm__ ("add %%ebx,%%eax\n\t" "mov %%ebx,%%ecx" : "=c"(output_variable) : "b"(first_operand),"a"(second_operand) : );
  • 为每个操作数分配一个名称并在扩展程序集模板中使用该名称可能更具可读性。类似__asm__("add %[iop1],%[iop2]\n\t" "mov %[iop1],%[ovar]" : [ovar]"=c"(output_variable) : [iop1]"b"(first_operand),[iop2]"a"(second_operand) : );
  • 如果 david wohlferd 来了,他可能会在不必要的时候advise against inline assembly,并且由于add 更改了标志,因此将"cc" 添加到clobber 列表中是一个好习惯(GCC 与 x86 一起工作,这实际上不是必需的)
猜你喜欢
  • 2012-10-20
  • 1970-01-01
  • 2011-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-11
  • 2015-12-23
  • 1970-01-01
相关资源
最近更新 更多