openEuler汇编语言(2)

举报
云舒云卷 发表于 2020/05/18 11:27:04 2020/05/18
【摘要】 上一期中我们介绍了一些 ARM 汇编语言的编程方法,这一期我们介绍一下 ARM 内嵌汇编器并尝试分析一下 openEuler 中的一段汇编代码。

一、内核汇编器[1]

C/C++ 编译器中包含了内嵌汇编器,使用这些内嵌汇编器可以在 C 或 C++ 代码中使用大部分 ARM 指令和 Thumb 指令。内嵌汇编指令中,作为操作数的寄存器和常量可以是 C 或 C++ 表达式,其类型包含 char、short 和 int 型。汇编器将这些量视为无符号数,也就是说如果要使用有符号数其符号位需要程序员自己处理。

在使用内嵌汇编指令时,一般不需要指定物理寄存器,编译器一般会作自动分配。若在内嵌汇编指令中使用物理寄存器,那么编译器会在使用前后保存和恢复这些物理寄存器中的值,从而使得这些物理寄存器表现得像被内嵌汇编指令临时使用而不影响其他程序运行。但物理寄存器的使用也是有限制的,例如有一些寄存器如sp在做特定用途时编译器不能恢复它的值,再如不能直接向 pc 寄存器中写入值,程序的跳转只能通过 b 和 bl 指令实现。汇编指令使用的寄存器数目不要过多,否则可能会在分配物理寄存器时造成冲突,编译器发现冲突时会报错。

内嵌汇编器会对一些指令进行展开操作,如一些乘法指令可能会被展开为一系列加法和移位指令。内嵌汇编器不支持内存分配操作,内存分配操作需要用 C/C++ 语句完成。

在 ARM C 语言中,内嵌汇编指令的一般格式如下图所示:

而在 ARM C++ 程序中,除了上述格式,还可以使用如下格式:

这种格式不支持在字符串中携带注释。下图展示了一个使用 ARM C 语言内嵌汇编的例子。在这个例子中,函数中变量x被汇编指令 ADD 自加一并返回,编译器为 x 自动分配了物理寄存器,1前面的#表示立即数。


二、openEuler 汇编代码分析举例

下面我们来尝试具体分析一段 openEuler 中的汇编代码。这段代码在 openEuler 代码仓库的 kernel/arch/arm64/kernel/entry.S 文件中可以找到。

上图中这段代码用于 task_struct 切换时寄存器的保存与恢复,x0 寄存器保存了切换前 task_struct 结构体的地址,x1 保存了切换后结构体的地址。我们可以看到这段代码首先设置保存切换前寄存器的内存地址(x8 寄存器),然后将切换前寄存器编号为 x19-x29 的寄存器以及lr寄存器都保存到了以 x8 中地址为栈底的栈中,其中还包含了切换前 sp 寄存器中的栈指针。然后代码找到了保存下一个 task_struct 相关状态的栈的栈底地址(也保存在 x8 中),将栈中的内容恢复到对应的寄存器中,包括 lr 寄存器和 sp 寄存器。在这段代码中,load 和 store 指令都使用的是 post-indexed 寻址方式,也就是先使用x8寄存器中的内存地址,再将这个地址加上立即数16。

三、结语

本期我们考察了 ARM 内嵌汇编器和 C/C++ 与 ARM 汇编指令混合编程的方法,在下一期我们将进入一个新的话题:操作系统的中断。







参考文献


[1]《ARM体系结构编程(第二版)》,杜春雷著。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。