Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
GCC内联汇编到二进制 在C或C++中,可以通过以下方式实现内联汇编指令: asm("assembly code");_Gcc_Assembly_Compilation - Fatal编程技术网

GCC内联汇编到二进制 在C或C++中,可以通过以下方式实现内联汇编指令: asm("assembly code");

GCC内联汇编到二进制 在C或C++中,可以通过以下方式实现内联汇编指令: asm("assembly code");,gcc,assembly,compilation,Gcc,Assembly,Compilation,或 例如: 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++变量之间交换值:更多信息 我的问题是:编译器是否将每条内联汇编指令直接转换为二进制指令?还是这只是一种“模仿”?这意味着

例如:

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++变量之间交换值:更多信息

我的问题是:编译器是否将每条内联汇编指令直接转换为二进制指令?还是这只是一种“模仿”?这意味着,我想知道您是在访问处理器的寄存器,还是代码中处理的所有数据都存储在堆栈中,模拟汇编指令。如果这个问题是愚蠢的,很抱歉。


当您使用“asm”或“asm”关键字时,GCC/G++会将字符串解析为汇编指令。如果使用'extended assembly',即在字符串后面包含冒号,以便使变量与寄存器的'input/output'交互,则内联汇编程序将执行简单的替换,如以下示例所示:


__asm\uuuu(“\
添加%ebx,%eax;\
mov%ebx,%ecx;\
“:”=c(输出变量):“b”(第一个操作数),“a”(第二个操作数):/*此处不需要任何内容*/)

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


在双引号之间的指令之后,可以添加三个冒号,在前两个冒号之间,声明将接收输出的变量。注意,“=c”(输出变量)意味着存储在ecx寄存器末尾的值将转发到()之间的变量

在最后两个冒号之间,声明将用作输入的变量/值,因此在代码开始时,括号之间的值被分配给用引号之间的字母表示的寄存器(使用comas进行多个输入)

在最后一个冒号之后,是一个被阻塞的寄存器列表。但是,在这种特殊情况下,这是可选的,没有用处。更多关于整个GCC内联程序集的信息

总之,执行过程如下:

  • 将输入值(如有)替换到相应的寄存器中
  • 从汇编到二进制的转换
  • 将输出加载到指定的变量中(如果有)

因此,简短的回答是“是”
,一旦代码被编译成机器语言,转换将是1对1,就像普通汇编程序一样,因此它将使用实寄存器



GCC的内联汇编程序执行简单的替换(如果使用扩展汇编程序模板),但将指令以单个ASM语句的形式输出到代码中。因此,是的,一旦编译成代码,它将使用真正的寄存器。这当然是假设程序不是在模拟器中运行的。谢谢,我刚才有点怀疑。我忘了说每条装配线末尾的反斜杠是为了避免换行,以便使用一对引号。而且,每个汇编指令都必须以分号结尾,虽然这只是为了帮助内联汇编解析器也应该指出,您的示例将ebx添加到eax中,并将结果存储到eax中。将ebx移动到ecx,实际上将ebx设置为第一个操作数的内容,而不是添加的值。每行不需要分号。
\n
换行符就可以了。最好是
\n\t
,如果您使用带有
-S
选项的GCC来输出由GCC生成的汇编代码,那么它的格式会更好。如果您单独引用每一行,则可以完全避免使用行继续符。代码中的一个错误是,使用扩展内联汇编程序寄存器名时,需要
%%
而不是
%%
。这也会起作用:
\u asm\u(“添加%%ebx,%%eax\n\t”“mov%%ebx,%%ecx”:“=c”(输出变量):“b”(第一个操作数),“a”(第二个操作数):)更具可读性的方法是为每个操作数指定一个名称,并在扩展程序集模板中使用该名称。类似于“
”[iop1]、%[iop2]\n\t”mov%[iop1]、%[ovar]:[ovar]“=c”(输出变量):[iop1]“b”(第一个操作数)、[iop2]“a”(第二个操作数):)
如果david wohlferd来了,他可能会在不必要的时候来,因为
add
更改了标志,所以将
“cc”
添加到clobber列表是一个好习惯(GCC与x86的工作方式实际上并不需要)
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 */