实模式BIOS例程和保护模式

时间:2010-09-02 03:14:19

标签: assembly operating-system x86 x86-16 protected-mode

我正在做一些操作系统实验。到目前为止,我的所有代码都使用实模式BIOS中断来操作硬盘和软盘。但是,一旦我的代码启用了CPU的保护模式,所有实模式BIOS中断服务程序将不可用。我怎么能R / W硬盘和软盘? 我现在需要做一些硬件驱动吗?我该如何开始?这是操作系统如此难以开发的原因之一吗?

我知道硬件都是通过读取和写入某些控制或数据寄存器来控制的。例如,我知道硬盘的命令块寄存器范围从0x1F0到0x1F7。 但我想知道PC平台上这么多不同硬件的寄存器地址是否相同?或者我必须在使用之前检测到它?如何检测它们?

由于我不确定如何在保护模式下使用R / W软盘或硬盘,我现在必须使用BIOS中断将所有必要的内核文件从软盘加载到内存中。但如果我的内核文件超过实际模式1M空间限制,我该怎么办?

对于任何回复,我都表示深深的谢意。

更新

我依旧回忆起有一种方法可以先切换保护模式然后切换回实模式。然后我们可以在保护模式下使用BIOS例程。也许我记得错了。有人记得吗?

9 个答案:

答案 0 :(得分:5)

虽然可能在保护模式和实模式之间切换,但几乎可以肯定你想要做什么。这就是286上的事情(非常笨拙,因为它没有故意支持从保护模式切换回实模式)。但是,从386开始,他们添加了一个V86模式,可以作为保护模式下的任务运行。

如果您想从保护模式使用BIOS,这几乎可以肯定是做事的方式。基本上你可以创建一个V86任务,切换到它使用BIOS,然后切换回另一个任务来执行保护模式代码。

如果你想玩这个,你可能想看一下DJGPP,这是一个DOS扩展器(基本上,就像我刚刚描述的一个程序来处理切换到/退出V86任务根据需要处理磁盘I / O等,以及相当旧版本的gcc的端口,这样你就可以编写在其上运行的代码。

DOS扩展器的商业市场现在基本上已经死亡,因此至少有一个以前商业化的DOS扩展器(HX)现在可用作开源。如果您打算使用它,您可能希望将它与OpenWatcom编译器一起使用。

编辑:至于如何读取超过1 MB的文件(例如),它很简单但很笨拙:以块的形式读取数据,当你完成读取后,你要重新映射内存,或者复制内容,将你读到的内容写到你真正想要的地方,然后阅读另一个块。

就与硬件的谈话而言:很大程度上取决于你是否只想要在某种程度上起作用的东西,或者你是否想要充分利用现有的硬件。只需使用基本的IDE端口,您就可以与几乎任何非真正古老的硬盘驱动器进行通信 - 但是从硬件中获取最多的功能是相当多的工作。 IDE / ATAPI驱动器使用了大约六种不同的DMA模式,每种模式的设置都略有不同。其中有一些已经足够大了,你可能不关心它们,所以你可能只想直接支持最新的几个,而其他任何东西都会回归到基本(非DMA)传输。

答案 1 :(得分:2)

似乎您的问题不是如何与硬件通信(设备驱动程序会解决问题),因为BIOS界面对您来说已经足够了。

相反,您需要知道如何在受保护模式环0(无限制地访问BIOS调用和所有其他特权指令)和应用程序代码通常存在的保护模式环3之间进行通信。这是系统调用。几乎所有架构都以特权模式运行中断处理程序,因此软件中断是实现系统调用的一种方式,x86还提供了syscall指令,该指令针对此目的进行了优化。

当然,您可以使用平面内存模型在环0中运行所有内容,您可以直接访问所有内存。

Ring 0 / ring 3是x86术语,但是所有带有MPU的系统都支持某种特权模式的概念,它允许通过物理地址访问内存(对于分离内存 - I / O体系结构,访问所有I) / O空间)。

答案 2 :(得分:1)

如果您使用旧版IDE,所有硬件都将以相同的方式进行通信 - 您不必担心编写自定义驱动程序(尽管如果您做得足够远,您会发现即使他们都说他们关注相同的规格,他们都有他们有趣的怪癖)

http://www.t13.org/http://www.t10.org是您可以找到相关规格的地方 - 如果您有勇气,也可以编写SATA驱动程序 - 您可以在英特尔网站上找到AHCI规范( http://www.intel.com/technology/serialata/ahci.htm

答案 3 :(得分:1)

如果您希望代码从32位模式读取硬盘(或USB密钥),您可以从我的操作系统项目PwnOS中找到一些代码。它不支持DMA或任何东西,但基础工作。具体地说,trunk / Core / IO / ATA Driver.asm包含用于读取ATA设备的代码,例如, harddrive(没有幻数!:D)

我决定不编写用于编写设备的代码,因为我不想冒风险,但它非常相似。这些规格可以在第一个谷歌热门节目“cottontail os dev”中找到(你需要ATA / ATAPI-6文件),但它们有点难以理解。

如果您对此有任何疑问,请随时提出。我也有代码可以设置为64位模式,以及我专门为OS开发设计的汇编语言编辑器(搜索Inventor IDE),因为它内置了16个汇编和链接定义的地址和文件偏移处的位,32位和64位代码。这样,你可以专注于你感兴趣的部分,而不是绒毛。

答案 4 :(得分:1)

V86:是的,如果要设置操作系统:

尝试这个(专为长模式设计,但应该可以工作。我没有测试过这个YET,我认为没有理由它不会工作。问题不是nasm,它的ld。)

LD H8s 16位ELF / aout references.This是从GRUB加载的标准。

我知道32位CS是关闭的,我需要仔细检查它的位置。否则它看起来不错。

很难找到代码。

-     ;修改为32位??

;this code is placed somewhere after 10000h
;-----we're in LONG MODE-----
  mov          dword [.stckptr], esp   ;first of all save stack
  sgdt         [.gdtv32]               ;save your gdt pointer
  lgdt         [.gdtv16]               ;load a new one
  sidt         [.idt32]                ;save your idt pointer
  lidt         [.idt16]                ;load real mode idt
  ;far jump in long mode is not possible, do a trick
  push         DESC_REAL
  push         @f-10000h               ;this is CS*10h, modify if needed!
  retfd
.stckptr:
  dd           0
  align        16
.gdtv32:
  dw           0
  dd           0
  align        16
.gdtv16:
  dw           .gdtend-.gdt-1
  dd           .gdt,0
  align        16
.gdt:
  dd           0,0                      ;null descriptor
DESC_DATA=8                                 ;descriptor in YOUR GDT (modify)
DESC_LONG=$-.gdt
  dd           00000000h,00209800h      ;32 bit  mode cs -MOD ME
DESC_REAL=$-.gdt
  dd           0000FFFFh,00009801h      ;16 bit real mode cs (modify base if needed!)
.gdtend:
  align        16
.idt32:
  dw           0
  dd           0
  align        16
.idt16:
  dw           3FFh
  dd           0
  USE16

;-----we're in COMPATIBLITY MODE-----
  ;disable paging and protmode at once
@@:   mov          eax, cr0
  and          eax, 7FFFFFFEh   
  mov          cr0, eax

  ;set up real mode segment registers and stack
  mov          esp, realmode_stack_top          ;modify it to your needs!
  xor          ax, ax
  mov          ds, ax
  mov          es, ax
  mov          fs, ax
  mov          gs, ax
  mov          ss, ax
  ;convert long mode rip to real mode cs:ip
  ;jmp CS:(pmode address)-CS*10h

  jmp          1000h:@f-10000h                  ;modify if needed!
;-----we're in REAL MODE-----
@@:   ;***********call some BIOS interrupt here**********
  mov          ax, 3
  int          10h


  ;switch back to long mode
  mov          eax, cr0
  or           eax, 80000001h
  mov          cr0, eax                         ;enable protmode and paging

  ;jmp         DESC_LONG:@f
  db           66h
  db           0EAh
  dd           @f
  dw           DESC_LONG
  USE32
;-----we're in protected MODE-----
@@:   lgdt         [cs:.gdtv32]                    ;restore gdt
  mov          ax, DESC_DATA                   ;read YOUR DATA descriptor to selectors
  mov          ds, ax
  mov          es, ax
  mov          fs, ax
  mov          gs, ax
  mov          ss, ax
  lidt         [.idt32]                        ;restore idt
  mov          rsp, qword [.stckptr]           ;restore stack
  ;must be a non rip-relative jump
  mov          eax, @f
  jmp          eax
@@:

  ;AS WE WERE!

答案 5 :(得分:0)

如果您正在编写操作系统,它确实需要为其需要使用的任何硬件(包括存储设备)提供设备驱动程序。如果你想在这么早的阶段避免需要驱动程序,你可以考虑使用像grub这样的现有引导加载程序,但最终你还是需要它们。

答案 6 :(得分:0)

该项目现在是一个旧项目,但犹他州的OSKit项目 - 可能仍然在现代机器上运行,因为其他20世纪90年代后期的操作系统仍然可以在今天的PC上找到RAM和磁盘驱动器? - 是一个独立于任何特定操作系统的设备驱动程序堆栈构建,因此您只需编写C代码即可开发自己的内核。

有点整洁;你可以编译“Hello,world”。在C中对抗OSKit并获得一个可以启动的操作系统,并打印出“Hello,world”。然后停了下来: - )

无论如何,如果你真的在进行“操作系统实验”,你可能想尝试一下 - 或者至少使用它的代码作为如何启动和运行某些驱动程序的指南。当然,如果你真的不那么做“操作系统实验”而更多的是“学习关于x86的模糊事实”,那么它可能比你想要的更多。 : - )

http://www.cs.utah.edu/flux/oskit/

答案 7 :(得分:0)

有一组关于保护模式here的教程。 Tut15和tut16在v86模式下有效地运行DOS和BIOS,所有中断都有效。

答案 8 :(得分:-1)

ATAPI设备使用相同的端口。你可以模拟DPMI以超过1MB + 64k的限制,但是,学习保护模式。