一、系统函数和普通函数
他们俩之间的区别是什么?
举个例子 进入编程的第一个demo是hello world!
我们看到的:我们调用了一个输出函数实现的
我们没看到的:如果函数的操作涉及到了权限在内核态的要求时,就要涉及系统
程序是运行在用户态的,但是有些是用户态权限无法操作的例如端口读写
特权指令
二、简单的实现
我的输出函数是通过端口的读写操作实现的,这样我用户态的函数不能调用我的输出函数进行显示了。权限不够。
我应该实现一个系统函数提供给我的用户态程序使用。
参考上面的典型实现过程。
这里复习下为什么能够通过中断实现这一个伟大的任务,因为中断,门一类的,有这个神奇的作用对权限的跨越,例如最近了解的linux的su命令。
1.安装了0x80号中断来进行系统函数服务
/** *安装实例化0x80号服务 *用户态的级别 */ void init_sys_call(){ put_str("Sys call interrupt init is start!\r\n"); make_idt_description((unsigned int)system_interrupt,(unsigned int)0x0028,(unsigned int)0xEE00,(unsigned int)0x80); }
2.这个中断的实现
这里可能有几个地方疑惑,看于渊书上的时候
1.save的地方直接放内存,因为前面是call调用所以放了一个地址进去了
2.总段居然用ret,你会发现在save的时候他保存了返回进程的地址,所以又算是切换原进程
;========================================================== system_interrupt: cli call save call [sys_call_table+eax*4] sti ret ;==========================================================;寄存器信息保存;因为是调用的所以有个如入栈了,这里只有系统函数使用才调用save: pushad push ds push es push fs push gs ;堆栈用内核的堆栈 mov esi,esp mov esp,StackTop ;这里程序的基本用内核级别的了 ;放一个进程的入口地址 push restart ;跳转回刚进来的位置 jmp [esi+12*4] ;==========================================================
3.简陋的系统表
#define _NR_PUT_STRING 0 //输出函数#define _NR_EXIT 1 //程序终止void sys_put_string();//系统输出函数别的地方不用unsigned int sys_call_table[]={ (unsigned int)sys_put_string//函数输出 };
4.真正的实现
因为我之前实现过输出的函数这里也懒得改了直接用了,所以又多了一层
extern put_string[bits 32]global sys_put_strglobal sys_put_string;======================================================================== sys_put_string: ;显示0终止的字符串并移动光标 push ebx call put_string add esp,4 ret ;段间返回;--------------------------------------------------------------- ;系统输出函数使用sys_put_str: mov eax,0x00 mov ebx,[esp+4] int 0x80 ret
三、最后
整体的大流程 1.对中断说我要找谁谁谁 2.中断保存环境 3.寻找谁谁谁 4.根据刚保存的环境当做任务切换回去了