贺邦+原创做品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000ubuntu
使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用,理解系统调用的工做机制。安全
编写两段代码,分别使用库函数API和C代码中嵌入汇编代码,源码以下:函数
uidgid.c(使用库函数API方式):ui
程序中经过调用getuid()和getgid()函数来获取当前执行用户uid和gid操作系统
参考:《Advanced Programming in the UNIX Environment》指针
uidgid_asm.c(使用C代码中嵌入汇编代码方式):blog
内嵌汇编代码版本源码中将原来两行经过API函数获取uid和gid的代码注释掉,用汇编代码替换。开发
首先将ebx寄存器清零,表示无参数传入。get
而后分别将0x18和0x2f(十进制24和47)赋值给eax寄存器,表示须要调用的系统调用号,24为getuid,47为getgid。源码
执行int 0x80来执行系统调用。
以后eax寄存器保存了返回值,将它分别赋值给输出uid或gid变量。
完成整个汇编代码的系统调用。
分别编译两个源码文件、执行系统id命令以及两个编译好的程序
上面的截图分别表示普通用户ubuntu和管理员用户root分别执行系统自带命令id,库函数API方式uidgid,内嵌汇编方式uidgid_asm这三种方式运行获得的结果是同样的。
经过实验执行结果可知,程序成功完成了系统调用获取当前用户uid和gid的操做,经过内嵌汇编代码能够清晰的看出调用系统调用的工做过程。
首先将ebx寄存器清零,表示无参数传入。
而后分别将0x18和0x2f(十进制24和47)赋值给eax寄存器,表示须要调用的系统调用号,24为getuid,47为getgid。
执行int 0x80来执行系统调用。
以后eax寄存器保存了返回值,将它分别赋值给输出uid或gid变量。
完成整个汇编代码的系统调用。
在Linux系统中是经过激活0x80中断来触发系统调用的,须要调用的系统调用号实现赋值给eax存储器,若是有传入参数可赋值给ebx寄存器,若是多于1个则按顺序赋值给ebx、ecx、edx、esi、edi、ebp,若是超过6个则经过指针变量指向另外一片堆栈区,若是无参数传入则赋值为0。
虽然Intel X86 CPU有4种执行级别0~3,可是在Linux系统中仅使用了0和3级,分别表示内核态和用户态。
一些涉及底层、硬件、核心的操做必须在内核态下才容许执行,为操做系统程序和驱动程序专享,普通程序仅能执行在用户态下。若是普通程序须要涉及内核态的操做,就须要经过系统调用来实现。这样作的好处是屏蔽平台相关操做下降了软件开发难度,加强了系统安全性,使程序具备更好的移植性(Linux系统及其余Unix系统遵循统一标准,系统调用基本同样)。