Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2112744
  • 博文数量: 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-08-17 15:57:56

《操作系统真相还原》 与 《Orange'S:一个操作系统的实现》都参考了
在上一篇文章中mbr读取了硬盘上的一个sector到0x9000,然后跳到了0x9000运行
1. 第一次写的loader.S
  1. org 0x9000
  2. jmp begin

  3. TYPE_0 equ 0x0

  4. S_0 equ (0x0<<4) ;s=0-->gate
  5. S_1 equ (0x1<<4) ;s=1-->data/code

  6. DPL_0 equ (0x0<<5) ;privilege level
  7. DPL_3 equ (0x3<<5)

  8. P_0 equ (0x00<<7) ;not in memory
  9. P_1 equ (0x01<<7) ;in memory

  10. AVL_0 equ (0x00<<8)

  11. DB_0 equ (0x00<<10) ;16bit data&code
  12. DB_1 equ (0x01<<10) ;32bit data&code

  13. G_0 equ (0x00<<11) ;g=0,byte
  14. G_1 equ (0x01<<11) ;g=1,4K

  15. TI_0 equ (0x0<<2) ;TI=0,gdt
  16. TI_1 equ (0x1<<2) ;TI=1,ldt

  17. RPL_0 equ (0x0)

  18. %macro DESC 3
  19.     dw %1 & 0xFFFF ;limit[0-15]
  20.     dw %2 & 0xFFFF ;base[0-15]
  21.     db (%2>>16)&0xFF ;base[16-23]
  22.     db (%3&0xFF) ;prop[0-7]
  23.     db (((%1>>8)&0xF) | (%3>>4)&0xF0) ;limit[16-19]prop[8-11]
  24.     db (%2>>24) & 0xFF
  25. %endmacro
  26. gdt_base: DESC 0, 0, 0
  27. gdt_code: DESC 0xFFFF, 0x0, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1)
  28. gdt_video: DESC 0xFFFF, 0xB8000, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1)

  29. gdt_ptr:
  30.     dw 24 ;gdt_limit: 8*3=16, only 3 gdt item
  31.     dd gdt_base ;gdt_base

  32. select_code equ (0x01<<3)|TI_0|RPL_0
  33. select_video equ (0x02<<3)|TI_0|RPL_0
  34. begin:
  35.     ;----------------- 打开A20 ----------------
  36.     in al,0x92
  37.     or al,0000_0010B
  38.     out 0x92,al

  39.     ;----------------- 加载GDT ----------------
  40.     lgdt [gdt_ptr]

  41.     ;----------------- cr0第0位置1 ----------------
  42.     mov eax, cr0
  43.     or eax, 0x00000001
  44.     mov cr0, eax

  45.     ;----------------- 跳到保护模式 ----------------
  46.     jmp select_code:protect_mode
  47. protect_mode:
  48.     mov ax,select_video
  49.     mov gs,ax
  50.     mov byte [gs:160], 'P'
  51.     jmp $
1.2 看需不需要改mbr
  1. cong@msi:/work/os/code/3pm$ ls -l loader.bin
  2. -rw-rw-r-- 1 cong cong 86 Aug 17 14:24 loader.bin
才86个字节,mbr是读了512个字节,这儿不到512字节,所以不需要修改mbr.S
下面开始分析问题
2. 
2.1.a 第一次调试
  1. (0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b          ; ea5be000f0
  2. <bochs:1> b 0x9000                      -->因为把代码加载到了0x9000,所以这儿直接到0x9000执行
  3. <bochs:2> c
  4. (0) Breakpoint 1, 0x00009000 in ?? ()
  5. Next at t=156817505
  6. .....
  7. <bochs:11>
  8. Next at t=156817513
  9. (0) [0x000000009035] 0000:00009035 (unk. ctxt): jmpf 0x0008:903a ; ea3a900800    -->向保护模式跳转
  10. <bochs:12>
  11. (0).[156817513] [0x000000009035] 0000:00009035 (unk. ctxt): jmpf 0x0008:903a ; ea3a900800  
  12. Next at t=156817514
  13. (0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0 -->这儿发现不对了,这儿是复位了
2.1.b 第一次修改
  1. cong@msi:/work/os/code/3pm$ diff ./loader.S loader.S_bad
  2. 4,5c4
  3. < TYPE_8 equ 0x8 ;code -->exec
  4. < TYPE_2 equ 0x2 ;data -->r/w
  5. ---
  6. > TYPE_0 equ 0x0
  7. 38,39c37,38
  8. < gdt_code: DESC 0xFFFF, 0x0, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_8)   -->code段加上可执行权限
  9. < gdt_video: DESC 0xFFFF, 0xB8000, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_2)   
  10. ---
  11. > gdt_code: DESC 0xFFFF, 0x0, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1)          -->原先code段没有可执行权限
  12. > gdt_video: DESC 0xFFFF, 0xB8000, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1)
2.2.a 第二次调试
  1. (0) [0x000000009039] 0000:00009039 (unk. ctxt): jmpf 0x0008:903e ; ea3e900800
  2. <bochs:15>
  3. Next at t=313385561
  4. (0) [0x00000000903e] 0008:0000903e (unk. ctxt): mov eax, 0xe88e0010 ; b810008ee8    -->这儿的确是跳到903e上面来了,但是还是乱的
  5. <bochs:16>
  6. Next at t=313385562
  7. (0) [0x000000009043] 0008:00009043 (unk. ctxt): mov byte ptr gs:[esi], 0xa0 ; 65c606a0
  8. <bochs:17>
  9. Next at t=313385563
  10. (0) [0x000000009047] 0008:00009047 (unk. ctxt): add byte ptr ds:[eax+101], dl ; 005065
  11. <bochs:18>
  12. (0).[313385563] [0x000000009047] 0008:00009047 (unk. ctxt): add byte ptr ds:[eax+101], dl ; 005065
  13. Next at t=313385564
  14. (0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
  15. <bochs:19>
  16. Next at t=313385565
  17. (0) [0x0000000fe05b] f000:e05b (unk. ctxt): xor ax, ax ; 31c0
2.2.b第二次修改
  1. 63 [bits 32]               -->加入这个标签,使得这儿编出来的是32位的代码
  2. 64 protect_mode:
2.2.c 对比一下两次生成的二进制代码
xxd ./loader.bin
  1. 0000000: eb1e 0000 0000 0000 0000 ffff 0000 0098 ................
  2. 0000010: 4f00 ffff 0080 0b92 4f00 1800 0290 0000 O.......O.......
  3. 0000020: e492 0c02 e692 0f01 161a 900f 20c0 6683 ............ .f.    -->没有加[bits 32]标签
  4. 0000030: c801 0f22 c0ea 3a90 0800 b810 008e e865 ..."..:........e
  5. 0000040: c606 a000 50eb fe ....P..


  6. 0000000: eb1e 0000 0000 0000 0000 ffff 0000 0098 ................
  7. 0000010: 4f00 ffff 0080 0b92 4f00 1800 0290 0000 O.......O.......
  8. 0000020: e492 0c02 e692 0f01 161a 900f 20c0 6683 ............ .f.    -->加了[bits 32]标签
  9. 0000030: c801 0f22 c0ea 3a90 0800 66b8 1000 8ee8 ..."..:...f.....
  10. 0000040: 65c6 05a0 0000 0050 ebfe e......P..
2.3 运行结果就对了


2.4 虽然结果上是对了,但还有点小问题
  1. cong@msi:/work/os/code/3pm$ diff ./loader.S loader.S_ok
  2. 34c34
  3. < db (((%1>>8)&0xF) | (%3>>4)&0xF0) ;limit[16-19]prop[8-11]    -->arg1的前16位己填序,现在要填16-19位
  4. ---
  5. > db (((%1>>16)&0xF) | (%3>>4)&0xF0) ;limit[16-19]prop[8-11]   -->所以要右称16位
2.5 代码打包
3pm.rar (下载后改名为3pm.tar.gz)
2.6 下面分析一下代码
  1. cong@msi:/work/os/code/3pm$ cat loader.S
  2. org 0x9000                            --> org是条伪指令不会生成二进制的代码
  3. jmp begin                             --> jmp下面是数据,cpu区分不了数据与代码,防止cpu把数据当成代码就加上jmp,人为的控制cpu去执行代码段中的代码
 -->下面定义了一堆段属性
  1. TYPE_8 equ 0x8 ;code -->exec
  2. TYPE_2 equ 0x2 ;data -->r/w

  3. S_0 equ (0x0<<4) ;s=0-->gate
  4. S_1 equ (0x1<<4) ;s=1-->data/code

  5. DPL_0 equ (0x0<<5) ;privilege level
  6. DPL_3 equ (0x3<<5)

  7. P_0 equ (0x00<<7) ;not in memory
  8. P_1 equ (0x01<<7) ;in memory

  9. AVL_0 equ (0x00<<8)

  10. DB_0 equ (0x00<<10) ;16bit data&code
  11. DB_1 equ (0x01<<10) ;32bit data&code

  12. G_0 equ (0x00<<11) ;g=0,byte
  13. G_1 equ (0x01<<11) ;g=1,4K

  14. TI_0 equ (0x0<<2) ;TI=0,gdt
  15. TI_1 equ (0x1<<2) ;TI=1,ldt

  16. RPL_0 equ (0x0)
  17. -->宏中arg1=段界限,arg2=段基址, arg3=段属性
  18. %macro DESC 3                           -->这儿采用了《Orange'S:一个操作系统的实现》中的宏,用宏之后就比较直观
  19.     dw %1 & 0xFFFF ;limit[0-15]
  20.     dw %2 & 0xFFFF ;base[0-15]
  21.     db (%2>>16)&0xFF ;base[16-23]
  22.     db (%3&0xFF) ;prop[0-7]
  23.     db (((%1>>16)&0xF) | (%3>>4)&0xF0) ;limit[16-19]prop[8-11]
  24.     db (%2>>24) & 0xFF
  25. %endmacro
  26. gdt_base:  DESC 0, 0, 0                    -->第一个描述符为空
  27. gdt_code:  DESC 0xFFFF, 0x0, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_8)             -->代码段描述符
  28. gdt_video: DESC 0xFFFF, 0xB8000, (G_0|DB_1|AVL_0|P_1|DPL_0|S_1|TYPE_2)         -->显示段描述符

  29. gdt_ptr:
  30.     dw 24                ;gdt_limit: 8*3=24, 只预留了3个gdt描述符的段界限
  31.     dd gdt_base          ;gdt_base gdt的基地址就是gdt_base这个标签的地址

  32. select_code equ (0x01<<3)|TI_0|RPL_0
  33. select_video equ (0x02<<3)|TI_0|RPL_0

  34. begin:
  35.     ;----------------- 打开A20 ----------------
  36.     in al,0x92
  37.     or al,0000_0010B
  38.     out 0x92,al

  39.     ;----------------- 加载GDT ----------------
  40.     lgdt [gdt_ptr]

  41.     ;----------------- cr0第0位置1 ----------------
  42.     mov eax, cr0
  43.     or eax, 0x00000001
  44.     mov cr0, eax

  45.     ;----------------- 跳到保护模式 ----------------
  46.     jmp select_code:protect_mode
  47. [bits 32]
  48. protect_mode:
  49.     mov ax,select_video
  50.     mov gs,ax
  51.     mov byte [gs:160], 'P'
  52.     mov byte [gs:161], 0xA4
  53.     jmp $


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