使用库函数 API 和 C 代码中嵌入汇编代码两种方式使用同一个系统调用

Zzzzxp / 2024-11-11 / 原文

张晓攀+原创作品转载请注明出处+《Linux内核分析》MOOC课程https://mooc.study.163.com/course/1000029000

实验四——使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

本次实验采用4号系统调用write

一、使用库函数API

1.创建hello.c文件

vim hello.c

2.编译并运行

编译

gcc -o hello hello.c

运行

./hello

二、C代码中嵌入汇编代码

1.创建hello-asm.c文件

vim hello-asm.c

这段代码是使用内联汇编的C程序,它通过系统调用 write 向标准输出(即屏幕)打印字符串 "hello world!"。

①定义了一个 msg 字符串为 "hello world!",长度 len 为12。

②使用 asm volatile 来嵌入汇编代码,volatile 关键字告诉编译器不要优化这段汇编。

③汇编部分:

  • movl %2, %%edx: 将字符串长度 len 移入寄存器 edx,作为系统调用的第三个参数。
  • movl %1, %%ecx: 将 msg 的地址放入寄存器 ecx,作为系统调用的第二个参数。
  • movl $1, %%ebx: 文件描述符1(标准输出)传递给 ebx,作为第一个参数。
  • movl $4, %%eax: 系统调用号4,表示 sys_write,将其放入 eax
  • int $0x80: 执行系统调用。

④最后通过 int $0x80 触发系统调用,将消息输出到屏幕。

2.编译并运行

编译

gcc -o hello-asm hello-asm.c

运行

./hello-asm

总结

Linux 系统调用的工作机制可以包括以下几点:

  1. 用户态和内核态的切换:系统调用是用户程序请求操作系统内核服务的接口,调用时会从用户态切换到内核态。
  2. 系统调用号:每个系统调用都有一个唯一的调用号,用户程序通过 eax 寄存器传递调用号给内核。
  3. 参数传递:系统调用的参数通过寄存器(如 ebx, ecx, edx 等)传递,内核通过这些参数执行相应的操作。
  4. 中断触发:通过触发中断(如 int 0x80)来通知内核执行特定的系统调用。
  5. 返回结果:内核处理完请求后,将结果放回寄存器并返回用户态程序。