MyOS 之 转入32位,变量名设计

打算转入的单独放一次,main跟其他所有文件%include一下,boot文件与main文件也是按顺序来的。按顺序来的话,每个文件都要设定好偏移。

这种顺序填入的并不用担心标签重复的问题,但是%include需要担心,因此这里采用namespace。所有的在外部引用的函数都加上文件名前缀!根据include的顺序在文件名前加上序号。这样就可以每个文件引用序号小的,不允许引用序号大的。因此也应该在最开始设定好序号。

0_xxx是常量定义区

1_xxx是变量定义区

2_xxx是函数定义区,但不会调用别的函数

3_xxx表示会引用函数的函数定义区,这个是最危险的

但有一个问题是,如果改动标号,那就十分困难了。

但是太麻烦了,因此只是在文件名这么用,函数就不这么用了。

 

汇编命令都是大写

常量都是大写而且特别长

普通函数都是加上文件名前缀而且驼峰大写。

 CR0 是系统内的控制寄存器之一。控制寄存器是一些特殊的寄存器,它们可以控制CPU的一些重要特性。
     0位是保护允许位PE(Protedted Enable),用于启动保护模式,如果PE位置1,则保护模式启动,如果PE=0,则在实模式下运行。
     1 位是监控协处理位MP(Moniter coprocessor),它与第3位一起决定:当TS=1时操作码WAIT是否产生一个“协处理器不能使用”的出错信号。第3位是任务转换位(Task Switch),当一个任务转换完成之后,自动将它置1。随着TS=1,就不能使用协处理器。
     CR0的第2位是模拟协处理器位 EM (Emulate coprocessor),如果EM=1,则不能使用协处理器,如果EM=0,则允许使用协处理器。
     第4位是微处理器的扩展类型位 ET(Processor Extension Type),其内保存着处理器扩展类型的信息,如果ET=0,则标识系统使用的是287协处理器,如果 ET=1,则表示系统使用的是387浮点协处理器。
     CR0的第31位是分页允许位(Paging Enable),它表示芯片上的分页部件是否允许工作。
     CR0的第16位是写保护未即WP位(486系列之后),只要将这一位置0就可以禁用写保护,置1则可将其恢复。

     CR1是未定义的控制寄存器,供将来的处理器使用。

     CR2是页故障线性地址寄存器,保存最后一次出现页故障的全32位线性地址。

     CR3是页目录基址寄存器,保存页目录表的物理地址,页目录表总是放在以4K字节为单位的存储器边界上,因此,它的地址的低12位总为0,不起作用,即使写上内容,也不会被理会。

     CR4在Pentium系列(包括486的后期版本)处理器中才实现,它处理的事务包括诸如何时启用虚拟8086模式等

可以说十分重要的寄存器。

通过CR0切换寄存器时,要马上执行jmp来进行切换一下,因为CPU为了加快指令的执行速度使用了管道(pipeline)机制,前一条指令还在执行中时,就开始解释下一条指令,因为模式变了,所以就需要重新解释一遍,jmp实际上就是清除缓存的功能。其实它还是顺序执行的。

进入保护模式后,所有段的意义也变了,除了CS以外所有段寄存器的值都从0x0000变成了0x0008(gdt+1段,所有段都变成8了。。。),CS保持原状是防止造成混乱,但也会后面处理。

作者对于C语言文件也是费劲,它没办法直接运行。。。只能查看二进制然后挑地址,而且还有一些没有讲清楚。留到了应用程序。实际上,他又把代码重新腾了一遍,自此,1MB以内就没有什么作用了。1MB到2.44MB用来存软盘内容,后面30kb是空的,再后面2kb是IDT,再后面64kb是GDT,再后面512KB是bootpack.hrb(?)再后面1MB是一个栈,再后面直到4GB就是空了。

1. 首先,他是有一个从软盘腾到内存,然后又从内存腾到内存的一个过程的。

2. 因为有一个问题是,我们的确接下来是要跳到main函数运行而不是跳转到8200开始的地方运行,因此1mb那个1.44mb貌似没什么用啊,而且既然都已经存入磁盘了(从8200开始的)为什么还要存3遍呢?

现在我在吃饭,假设我是程序而我前面的桌子是数据。我知道桌子在哪,我也知道我的嘴在哪。我伸出筷子去夹菜,在保护模式下,程序段基址和数据段基址不一样,导致我前方的时空扭曲了,筷子伸到了别人的桌子上而我并不知道,所以上帝要把数据拷贝到别人的桌子上。那么既然我面前的桌子没用能不能不要了呢?也不行,因为桌子没了,我就移到了桌子的位置,而我收回的手就只能把菜送到自己的后脑勺了。

我是个吃货,不光胖自己身后桌子上的东西也不放过(坑爹的gcc会把字符常量放在代码段的后面)。我把筷子伸向背后,空间又扭曲了,筷子出现的位置离别人桌子的距离和我一样宽。上帝没法区分我和我背后的桌子,他干脆把我和桌子一起拷贝过去(因为程序长度不一定,稍微改动源码长度就会变),这样一来数据段中和我体型一样宽的地区都被浪费了。
数据段基址一般是0,否则操作一些硬件就会比较麻烦,比如显存从0xa0000开始,如果数据段基址不为0,代码在访问显存时就需要在原来的地址上减去这个数。但从0开始的问题就在于,上帝(处于实模式,在我运行之前运行并结束的负责复制内存和设置全局变量表的程序)一般离0不会太远,如果我实在太胖,那么上帝在复制我和桌子的过程中很可能把他自己也盖住了,上帝创世未捷身先死那我也不存在了。
可以在我和桌子前面加上一段为上帝留的空间0x0000-0x9000,这下上帝不怕被覆盖了。同时注意,在可执行文件中我的代码不能离上帝太近,否则我的复制可能盖住我自己,假如上帝代码从0x8000开始,应该在我和上帝之间留出0x1000的间隔。

这顿饭不容易啊,还是不要当吃货了。

不行,难度直线上升。

果然哈,代码是直接连着后面的,必须这样

进入保护模式后,6个段寄存器ES CS DS SS FS GS叫做段选择器,和实模式不同,保护模式的内存访问有自己的方式,

在保护模式下,尽管访问内存时也需要指定一个段,但传送到段选择器的内容不是逻辑段地址,而是段选择子。段选择子由三部分组成:

8是1000,正好是描述符索引1,第一个段描述符,gdt+1,其余都是0.

后面是3个0,因此至少是 10 000才对,也就是0x10

但得数为什么是0x1000,而不是0x0010呢?因为这是倒着的,远字节跳转的代码肯定没错。

  • 描述符索引——用来在描述符表中选择一个段描述符。
  • 描述符表指示器——TI=0时,在GDT表中;TI=1时,在LDT表中。
  • 请求特权级别——4个级别,0,1,2,3。

此时CS不能变,那么它此时还是在8200处,你要知道1*8跟2*8是啥区别,1*8是第一段,2*8是第二段,第一个段里所有ds,es全部被填8,CS则被填了2*8,这就是第二段,第二段是从280000开始的,但是跳转并不这么跳,它需要用到段标识符而不是直接跳。这个混合型size真的是不动~

jmp selector:0,的确是需要用到段选择子的。

罪魁祸首在这里:

第一个从0到4GB,第二个从xxx到这些,这些都是代码定义的啊?因此你最好先学学段问题。

0号是空区域(null sector),不能在那里定义段。

这些都是算出来的。

因此,最初时,GDT先在asmhead.nas里就有设定了,目的就是为了大致分段,跳转到32位可执行。但是为了IDT,还必须在C语言代码里再重新设置一遍,就是这样。段信息需要8个字节存储,而段寄存器只有16位,在保护模式下,段寄存器包含段描述索引(段选择子),8字节段信息(段描述符)为:【Base Address,Limit,Access】总共64位。

很难算,也很难看出原地址是什么。

它之所以复制两次,是因为整个1.44MB完全复制,你很难推断出bootpack是放在哪里的,而从bootpack开始复制,则非常容易找到它的地址。

进入32位后,就不可以调用BIOS了,因此在进入32位前还有一些额外操作。例如画面设定和得到键盘状态。(指示灯信息)

 

每日一个小常识:

汇编与C语言连用时,只能使用EAX,ECX,EDX这三个,因为其他寄存器C语言自己使用,用于记忆非常重要的值。

32 位的寄存器已经可以进行 4GB 的内存寻址了,但是似乎还不够,所以后来又发展出了 64 位寄存器,其中48位用来寻址,这下好了,至少目前感觉够用了。

伴随着64位处理器又出现了一种新的模式:IA-32e。

IA-32e 是基于保护模式的,也就是说也是通过段选择子、段描述符等来寻址的,但是和32 位保护模式不同的一点是,对于IA-32e来说,所有段描述符中的段基址都是0,段长度都是可寻址的最大长度,这样在分页情况下,段内偏移量直接就等于线性地址了,无需再经过公式计算。

IA-32为Intel Architecture 32-bit简称,即英特尔32位体系架构,在英特尔公司1985年推出的80386微处理器中首先采用。属于X86体系结构的32位版本,即具有32位内存地址和32位数据操作数的处理器体系结构,从1985年面世的80386直到Pentium 4,都是使用IA-32体系结构的处理器。通常也被称为i386、x86-32、x86等。

IA64是后来intel和惠普联合推出的64位体系架构,但是不兼容原有的32位体系结构的应用程序,导致市场惨淡。

后来AMD推出了兼容32位的64位集关于IA-32的扩展,之后改名为AMD64,Intel后来也采用该架构,称为x86-64或者x64。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值