使用库函数 API 和 C 代码中嵌入汇编代码两种方式使用同一个系统调用
张晓攀+原创作品转载请注明出处+《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 系统调用的工作机制可以包括以下几点:
- 用户态和内核态的切换:系统调用是用户程序请求操作系统内核服务的接口,调用时会从用户态切换到内核态。
- 系统调用号:每个系统调用都有一个唯一的调用号,用户程序通过
eax
寄存器传递调用号给内核。 - 参数传递:系统调用的参数通过寄存器(如
ebx
,ecx
,edx
等)传递,内核通过这些参数执行相应的操作。 - 中断触发:通过触发中断(如
int 0x80
)来通知内核执行特定的系统调用。 - 返回结果:内核处理完请求后,将结果放回寄存器并返回用户态程序。