雅乐网

计算机技术、学习成长

计算机 » 操作系统 » linux0.11系统调用,_syscall

linux0.11系统调用,_syscall

unistd.h

linux0.11 中,include/unistd.h 中定义了72个系统调用号

以及几个宏函数

这4个 syscall 函数可以用来展开成为系统调用函数,后面的数字表示函数有几个参数。它的形式参数

type 函数返回类型
name 函数名
atype 第一个参数类型
a 第一个参数
btype 第二个参数类型
b 第二个参数
ctype 第三个参数类型
c 第三个参数

使用syscall

以write为例, 在unistd.h中,write函数声明如下:

只要按照syscall的参数格式填上去

type 函数返回类型 int
name 函数名 write
atype 第一个参数类型 int
a 第一个参数 fd
btype 第二个参数类型 const char *
b 第二个参数 buf
ctype 第三个参数类型 off_t
c 第三个参数 count

lib/write.c 中是他的实现

展开后就变成了(为了展示清除额外手动添加了换行)

这是一个内嵌汇编,通过int 0x80 中断来实现系统调用。

第一个冒号后面是输出,输出的寄存器前面要有等号,”=a” 表示 输出存放在 eax 寄存器中,最终汇编结束时会赋值给 变量 __res

第二个冒号后面是输入,把输出和输入用到的寄存器按顺序编号(从输出寄存器开始从左到右,再从输入寄存器从左到右),”0″ 表示的是第一个寄存器,也就是输出用的eax,它的值被赋值为__NR_write, 也就是系统调用号。后面”b”, “c”, “d”表示寄存器ebx,ecx和edx,用来存放write的三个参数。可以用的寄存器符号表示表:

符号 表示 符号 表示
a eax m 使用内存地址
b ebx o 使用内存地址可以加偏移
c ecx I 使用常数0-31
d edx J 使用常数0-63
S esi K 使用常数0-255
D edi L 使用常数0-65535
q 动态分配可寻址寄存器

eax, ebx, ecx, edx

M 使用常数0-3
r 使用任意动态分配的寄存器 N 使用1字节常数0-255
g 使用通用有效地址、

(可寻址寄存器或内存地址)

O 使用常数0-31
A eax与edx联合(64位) = 输出操作数
+ 操作数可读可写 & 早期会变的操作数,表示使用完操作数之前,内容会被修改

int 0x80

在初始化的main函数中的sched_init中,有下面的代码

这句话设置IDT表,将0x80中断号和system_call函数进行绑定,调用int 0x80时,就会执行system_call函数。

include/asm/system.h

因此这个语句

宏展开后,变成了

第一个参数表示描述符的地址,0x80号中断的描述符地址就是&idt[0x80] , 第二个参数描述符类型,第三个参数是描述符特权级dpl,第四个参数是偏移地址

再展开,变成了

IDT表的表项

代码中两个”o” 分别是表项的低4个字节和高4个字节,序号是%1和%2

第一个输入  (short) (0x8000+(3<<13)+(15<<8)) 的二进制是

1110 1111 0000 0000

放到dx中,也就是edx的低2个字节,赋值给%2 ,也就是设置了

而edx的高2个字节是system_call偏移地址的高2个字节

dex的低2个字节是system_call偏移地址的低2个字节,复制给ax(eax的低2个字节)

eax的高2个字节是0x0008

表项赋值为:

system_call

kernel/system

通过 call sys_call_table(,%eax,4) ,call的是 sys_call_table + 4 * eax,4表示每个函数地址是4个字节。

sys_call_table是一个函数表,在 include/linux/sys.h中定义

write 的 调用号是4,和这里对应的。

 

如果文章对你有帮助,欢迎点赞或打赏(金额不限)。你的打赏将全部用于支付网站服务器费用和提高网站文章质量,谢谢支持。

版权声明:

本文由 原创,商业转载请联系作者获得授权。
非商业转载请注明作者 雅乐网 ,并附带本文链接:
https://www.yalewoo.com/linux0_11_syscall.html

上一篇:

下一篇:

我要评论

验证码*: 5 + 5 =