Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2150703
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2016-09-03 23:34:26

1.1 set_trap_gate(0,& divide_error);函数干了些什么?
main --> trap_init -->set_trap_gate

上图出自《Orange's:一个操作系统的实现》于渊 P51
set_trap_gate(0,& divide_error);
set_trap_gate(n, addr);
_set_gate(&idt[n],15,0,addr)
_set_gate(gate_addr, type, dpl, addr);
  1. #define _set_gate(gate_addr,type,dpl,addr) \
  2. __asm__ ("movw %%dx,%%ax\n\t" \          -->edx是addr的全部地址,这儿只用了低16位
  3. "movw %0,%%dx\n\t" \
  4. "movl %%eax,%1\n\t" \         -->eax的低16位是addr的低16位,eax的高16位是选择子
  5. "movl %%edx,%2" \             -->edx的低16位是属性,edx的高16位是addr的高16位
  6. : \                           -->movl一次移动4个字节,这样既填充了属性又填充了addr
  7. : "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \   -->0x8000-->P=1 dpl偏移是13,type偏移是8
  8. "o" (*((char *) (gate_addr))), \
  9. "o" (*(4+(char *) (gate_addr))), \
  10. "d" ((char *) (addr)),"a" (0x00080000))
edx=(char*)addr
eax=0x00080000
[0-3] -->0x00080000|(addr&0xFFFF)
[4-5] --> edx的低16位去填充属性
[6-7] --> edx的高16位去填充addr的高16位
都写到&idt[n]这个地方去了,idt是在head.s中分配了地址空间[0x54c0-0x5cc0]  -->idt 2k
设置完如下图所示:


1.2 关于属性
type=0xE=1110=14 是中断门
type=0xF=1111=15 是陷阱门

CPL: Current Privilege Level
DPL: Descriptor Privilege Level
RPL: Requested Privilege Level

1.3 问题1: 这儿为什么是0x80000呢

上图出自《Orange's:一个操作系统的实现》 P32
8 --> 1000 --> 描述符索引是1, TI=0(GDT), RPL=0
TI是Table Indicator,指示TI=0选择子是在GDT中,TI=1选择子是在LDT中

1.4 问题2: 这儿选择子=1有什么作用?
看看下面的图就明白了

上图出自《Linux内核完全注释(修正版v3.0).pdf》 P116
a. 中断入口地址 = 段基址:偏移值
段基址是选择子中的段基址,偏移值是中断门描述符中的偏移

b. 在head.s中设置的选择子1是内核的代码段
gdt:
    dq 0x0000000000000000
    dq 0x00c09a0000000fff                  -->selector=1,即内核的代码段
00   c09a   000000  0fff   -->段基址=0, 段界限=4096*0xFFF=16M
1.5 问题: 为什么set_trap_gate(0,& divide_error); 这儿要传 & divide_error? 
感觉只要 divide_error 就够了, 为什么要多一个&?
a.  测试程序

从测试程序中可以看到 add = &add 
b. 再加一点

从测试程序中可以看到 add = &add = *add
c. 反汇编看一下


add  &add *add 反汇编后都是一个地址
我的理解是这样的: 
编译器知道add是一个函数,那么就把 &add *add 都当add处理了.
1.6 C嵌入汇编
__asm__ ("assamble code":output : input : modify);
其中: 
   output 要加一个修饰符  =
   
a  b  c  d D  S -->eax ebx ecx edx edi esi
q --> 任意的4个通用寄存器(eax, ebx, ecx, edx)
r  --> 任意的6个通用寄存器(eax, ebx, ecx, edx, esi, edi)
g --> 表示可放在任意的地方,可放寄存器,也可放内存
i  --> 代
表整数立即数
$ -->立即数前缀, $8代表数字8

阅读(1769) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~