博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux 0.11 源码学习(七)
阅读量:6319 次
发布时间:2019-06-22

本文共 2296 字,大约阅读时间需要 7 分钟。

trap.c & Asm.s

trap.c和Asm.s主要完成的是系统中断和陷阱的初始化定义。

注:在80386体系的CPU中中断描述符表替代了中断向量表,IDT的描述符可以是中断门、陷阱门或者任务门。IDT中的中断门和陷阱门的定义如下:BYTE0/1(偏移底字节),BYTE2/3(选择子)、BYTE4/5(属性)、BYTE6/7 (偏移高字节)。通过两个字节的段描述符合四个字节的偏移就可以找到相应的目标代码地址。

因此在看trap.c和Asm.s的代码前,首先要分析下一部分system.h中的代码,如下:

#define _set_gate(gate_addr,type,dpl,addr) \__asm__ ("movw %%dx,%%ax\n\t" \ //下面四行汇编就是完成IDT描述符的填充    "movw %0,%%dx\n\t" \    "movl %%eax,%1\n\t" \    "movl %%edx,%2" \    : \ //无输出    : "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \//%0参数为IDT的BYTE4,5    "o" (*((char *) (gate_addr))), \//%1变量为内存gate_addr,即门描述符的低四字节    "o" (*(4+(char *) (gate_addr))), \ //%2变量为内存gate_addr+4    "d" ((char *) (addr)),"a" (0x00080000))//edx = addr, eax = 0x00080000; 0x0008为选择字,即对应GDT中的第二个描述符,代码段 #define set_intr_gate(n,addr) \ //n为中断索引    _set_gate(&idt[n],14,0,addr) // 14 0x0e属于中断门,DPL设置为0不允许用户态直接访问#define set_trap_gate(n,addr) \    _set_gate(&idt[n],15,0,addr) // 15 0x0f属于属于陷阱门,DPL设置为0不允许用户态直接访问#define set_system_gate(n,addr) \    _set_gate(&idt[n],15,3,addr) //调用门,DPL为3允许用户态访问

在trap.c和Asm.s中具体设置陷阱比较类似,以除零出错为例:

在trap.c的init函数中 set_trap_gate(0, &divide_error)。divider_error函数定义在Asm.s中如下:

divide_error:    pushl $do_divide_error //do_divide_error陷阱处理函数入栈

do_divide_error定义在trap.c中,如下:

void do_divide_error(long esp, long error_code){    die("divide error",esp,error_code);//打印当前出错进程的信息}

 

其他代码类似,诸如int 3中断或堆栈段错误。

int3:    pushl $do_int3    jmp no_error_codestack_segment:    pushl $do_stack_segment    jmp error_code

注:这里要值得注意的是do_XX函数的调用,是通过在no_error_code或者error_code中利用iret和堆栈实现的。其中no_error_code要比error_code少入栈一个参数error_code,即我们看到的do_divide_error中的第二个参数。如下:

error_code:    xchgl %eax,4(%esp)       # error code <-> %eax    xchgl %ebx,(%esp)        # &function <-> %ebx    pushl %ecx    pushl %edx    pushl %edi    pushl %esi    pushl %ebp    push %ds    push %es    push %fs    pushl %eax            # error code    lea 44(%esp),%eax     # offset //地址esp+44 赋值给eax,44是堆栈中寄存器长度和,参考赵博的书    pushl %eax    movl $0x10,%eax    mov %ax,%ds    mov %ax,%es    mov %ax,%fs    call *%ebx //调用具体的函数,C语言的入参是放在堆栈里的;    addl $8,%esp //跳过error code和function这8字节    pop %fs    pop %es    pop %ds    popl %ebp    popl %esi    popl %edi    popl %edx    popl %ecx    popl %ebx    popl %eax    iret

转载于:https://www.cnblogs.com/Fredric-2013/archive/2013/05/04/3058992.html

你可能感兴趣的文章
wordpress admin https + nginx反向代理配置
查看>>
管理/var/spool/clientmqueue/下的大文件
查看>>
centos 5.5 64 php imagick 模块错误处理记录
查看>>
apache中文url日志分析--php十六进制字符串转换
查看>>
浅谈代理
查看>>
基于jquery实现的超酷动画源码
查看>>
fl包下的TransitionManager的使用
查看>>
Factorialize a Number
查看>>
防HTTP慢速攻击的nginx安全配置
查看>>
Spring Boot2.0+中,自定义配置类扩展springMVC的功能
查看>>
参与博客编辑器改版,我的礼物 感谢51cto
查看>>
JavaWeb笔记——JSTL标签
查看>>
一些实用性的总结与纠正
查看>>
Kubernetes概念
查看>>
spring技术内幕读书笔记之IoC容器的学习
查看>>
自动生成四则运算题目
查看>>
Android学习系列(5)--App布局初探之简单模型
查看>>
git回退到某个历史版本
查看>>
HTML5基础(二)
查看>>
ue4(c++) 按钮中的文字居中的问题
查看>>