我正在做一些操作系统实验。到目前为止,我的所有代码都使用实模式BIOS中断来操作硬盘和软盘。但是,一旦我的代码启用了CPU的保护模式,所有实模式BIOS中断服务程序将不可用。我怎么能R / W硬盘和软盘? 我现在需要做一些硬件驱动吗?我该如何开始?这是操作系统如此难以开发的原因之一吗?
我知道硬件都是通过读取和写入某些控制或数据寄存器来控制的。例如,我知道硬盘的命令块寄存器范围从0x1F0到0x1F7。 但我想知道PC平台上这么多不同硬件的寄存器地址是否相同?或者我必须在使用之前检测到它?如何检测它们?
由于我不确定如何在保护模式下使用R / W软盘或硬盘,我现在必须使用BIOS中断将所有必要的内核文件从软盘加载到内存中。但如果我的内核文件超过实际模式1M空间限制,我该怎么办?
对于任何回复,我都表示深深的谢意。
我依旧回忆起有一种方法可以先切换保护模式然后切换回实模式。然后我们可以在保护模式下使用BIOS例程。也许我记得错了。有人记得吗?
答案 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的模糊事实”,那么它可能比你想要的更多。 : - )
答案 7 :(得分:0)
有一组关于保护模式here的教程。 Tut15和tut16在v86模式下有效地运行DOS和BIOS,所有中断都有效。
答案 8 :(得分:-1)
ATAPI设备使用相同的端口。你可以模拟DPMI以超过1MB + 64k的限制,但是,学习保护模式。