Linux内核C++中嵌入汇编代码的例子

以获取时间为例

Posted by MetaNetworks on May 18, 2020
本页面总访问量

博文以以下关机代码来讲解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include </usr/include/linux/reboot.h>
...
int Shutdown(int argc,char* argv[]){

    int result_code = -1;
    int shutdown_code = 88;

    int magic_1 = LINUX_REBOOT_MAGIC1;
    int magic_2 = LINUX_REBOOT_MAGIC2;

    int shutdown_command = LINUX_REBOOT_CMD_POWER_OFF;

    asm volatile(
        "movl %1,%%eax \n\t"
        "int $0x80 \n\t"
        "movl %%ebx,%0 \n\t"
        : "=m"(result_code)
        : "r"(shutdown_code),"ebx"(magic_1),"ecx"(magic_2),"edx"(shutdown_command)
    );
    printf("the result code is %d",&result_code);
}
...

其中关机需要两个幻数为的是防止误操作,防止系统出现错误导致误调用关机。

  • 两个幻数和关机指令是在/usr/include/linux/reboot.h中定义

Linux内核中,我们可以使用0x80系统中断调用号来实现系统调用。

中断调用汇总见博文:https://blog.csdn.net/xiaominthere/article/details/17287965

在C/C++中,我们使用asm volatile来内嵌汇编代码,注意:要分清楚32位和64位汇编

汇编结构:

1
2
3
4
5
6
__asm__(
	汇编语句模板:
  输出部分:
  输入部分:
  破坏描述部分; 
)

我们拿出关机代码中的汇编代码

1
2
3
4
5
6
7
8
asm volatile(
        "movl %1,%%eax \n\t"
        "int $0x80 \n\t"
        "movl %%ebx,%0 \n\t"
        : "=m"(result_code)
        : "r"(shutdown_code),"ebx"(magic_1),"ecx"(magic_2),"edx"(shutdown_command)
				: "eax"
   );

其中:

  • 表示寄存器的%需要双写转义。
  • %n表示后面传的第n个参数,比如上述的shutdown_code为第1个参数,result_code为第0个参数,等等。
  • "r"表示该变量放到某一个寄存器中,由编译器决定;ebx(variable)表示在执行这些汇编代码前,将相关C++变量值复制到ebx寄存器中
  • 最后的eax表示这段代码会破坏eax的原有内容

执行效果如下:

执行shutdown