C/C++中书写汇编指令

Posted mazhimazhi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++中书写汇编指令相关的知识,希望对你有一定的参考价值。

 

汇编语言的指令格式目前有两种不同的标准:Windows下的汇编语言基本上都遵循Intel风格的语法,比如:MASM、NASM,Unix/Linux下的汇编语言基本上都遵循AT&T风格的语法。 下面主要介绍Unix/Linux下的汇编,具体格式如下:

[名称[:]] 指令码 源操作数SRC,目的操作数DST ;注释

开发一个OS,尽管绝大部分代码只需要用C/C++等高级语言,但是和硬件相关部分的代码需要使用汇编语言;由于启动部分的代码有大小限制,使用精练的汇编可以缩小目标代码的Size;另外,对于某些需要被经常调用的代码,使用汇编可以提高性能。
如果我们选择的OS开发工具是GCC以及GAS的话,就必须了解AT&T汇编语言语法,因为GCC/GAS只支持这种汇编语法。下面介绍GCC的内嵌汇编语法。
GCC 支持在C/C++代码中嵌入汇编代码,这些汇编代码被称作GCC Inline ASM——GCC内联汇编。这是一个非常有用的功能,有利于我们将一些C/C++语法无法表达的指令直接潜入C/C++代码中,另外也允许我们直接写 C/C++代码中使用汇编编写简洁高效的代码。

1.基本内联汇编

 基本格式如下:

__asm__ [__volatile__] ( assembler template 
: [output operand list] /* optional */
: [input operand list] /* optional */
: [clobbered register list] /* optional */
);

(1)关键字“__asm__”,其实也可以写成“asm”。但是“asm”并不是所有版本的GCC编译器都支持的,而且有可能和程序中别的地方定义的变量或函数名冲突,所以用“__asm__”的话,兼容性会好一点。 

(2)“__volatile__”关键字,这个是可选的,其作用是禁止编译器对后面编写的汇编指令再进行优化。一般情况下,自己写的汇编代码肯定是自己进行设计优化过了的,如果编译器再进行优化的话,很有可能效果还不如不优化,而且也有可能会出现奇怪的错误,所以通常都会带上这个关键字。同样,“__volatile__”也可以写成“volatile”,但可能兼容性会没那么好。

(3)汇编代码由4部分组成,分别是汇编代码模板、输出操作数列表、输入操作数列表和修改寄存器列表,下面进行介绍。

1)汇编代码模板

汇编代码部分是必需的,所以即使一行汇编代码没有也需要传入空字符串(""),否则会报错。所有的汇编代码必须用双引号括起来。如果有多行汇编代码的话,每一条语句都要用双引号括起来,并且在代码后面要加上换行符(“\n”或者“\n\t”)。这样做是因为GCC会将汇编代码部分作为字符串形式直接传给汇编器,加上换行符后,汇编器就能准确知道哪些字符串表示的是一条汇编语句。同时,为了增加可读性,每条汇编语句都可以换行。

2)输入操作数列表与输出操作数列表

前面介绍了,第二部分和第三部分分别表示输出操作数列表和输入操作数列表。

输入操作数表示要作为汇编代码输入的C表达式,而输出操作数刚好相反,表示汇编代码处理完后要输出结果的C表达式。如果有多个输出或输入表达式,需要用逗号(“,”)将它们分隔开来。

可以再前面的汇编代码模板中直接应用定义的输出操作数和输入操作数,其用法是使用百分号(“%”)后面接一个数字,0表示定义的第一个操作数,1表示定义的第二个操作数,依次类推。下面举个例子:

__asm__("mov %0, %1, ror #1" 
            : "=r" (result) 
            : "r" (value)
        );

这里%0代表后面定义的第一个操作数,即输出操作数,代表C语言中的result变量。%1代表定义的第二个操作数,即输入操作数,代表C语言中的value变量。其作用是将value的值右移一位,然后保存到result中。

每一个操作数由三部分组成,分别是修改符(Modifier),限定符(Constraint)和C表达式,其中修改符是可选的。具体形式如下:  

"[modifier]constraint" (C expression)

 

修改符和限定符要用双引号括起来,而C表达式要用括号括起来。那么这些修改符和限定符又是什么呢?有什么作用呢?
我们接下来先来说说所谓的限定符。可以看出,操作数在这里的作用是将C语言定义的变量与汇编语言中要使用到的变量进行一一对应。但并不是所有的汇编指令都可以接受任何类型的变量作为输入或输出变量的,因此汇编器需要知道这些变量到底用在什么地方,从而帮助在传递之前做一些转换。常用的限定符主要有以下一些,而且汇编语句到底是ARM的还是Thumb的,对限定符的定义也会不同:

  

 

参考文章 :

(1)如何在C或C++代码中嵌入ARM汇编代码 https://blog.csdn.net/Roland_Sun/article/details/42921131

(2)汇编与C/C++内联嵌入汇编 https://blog.csdn.net/Levet/article/details/78516307

以上是关于C/C++中书写汇编指令的主要内容,如果未能解决你的问题,请参考以下文章

汇编笔记_1

实验二 汇编命令(伪指令)实验

汇编语言第一章

第一章总结

汇编语言第一章 基础知识 总结

实验1 用机器指令和汇编指令编程