如何在 NASM 程序集中使用 BIOS int 13h 从磁盘加载内核?

发布于 2024-08-07 04:17:33 字数 1229 浏览 4 评论 0原文

我已经被这个问题困扰了好几个星期了,不知道哪里出了问题,因为 NASM 没有给我任何错误。由于注释,该代码非常不言自明。

这是从 BIOS 加载的代码

 ;--------------------------------------------
 ; 'boot.asm'
 ; loaded from BIOS

 [org 0x7C00]
 [bits 16]

 ;--------------------------------------------

 main:
  mov ah, 0x0E  ; print function
  mov al, '.'   ; ascii char
  int 0x10   ; IO int

 resetdisk:
  mov ah, 0x00  ; reset function
  mov dl, 0x00  ; drive
  int 0x13   ; disk int
  jc resetdisk

 readdisk:
  mov bx, 0x8000  ; segment
  mov es, bx
  mov bx, 0x0000  ; offset

  mov ah, 0x02  ; read function
  mov al, 0x03  ; sectors
  mov ch, 0x00  ; cylinder
  mov cl, 0x02  ; sector
  mov dh, 0x00  ; head
  mov dl, 0x00  ; drive
  int 0x13   ; disk int
  jc readdisk
  jmp [es:bx]   ; buffer

 ;--------------------------------------------

 times 510 - ($ - $$) db 0x00
 db 0x55, 0xAA

这是应该(但没有)加载的代码

 ;--------------------------------------------
 ; 'load.asm'
 ; loaded from 'boot.asm'

 [org 0x8000]
 [bits 16]

 ;--------------------------------------------

 main:
  mov ah, 0x0E  ; print function
  mov al, '.'   ; ascii char
  int 0x10   ; IO int

  jmp $    ; hang

任何帮助将不胜感激。

帕特里克

I've been stuck with this for weeks now and have no idea where I'm going wrong because NASM hasn't given me any errors. The code is pretty self explanatory because of the comments.

this is the code that is loaded from the BIOS

 ;--------------------------------------------
 ; 'boot.asm'
 ; loaded from BIOS

 [org 0x7C00]
 [bits 16]

 ;--------------------------------------------

 main:
  mov ah, 0x0E  ; print function
  mov al, '.'   ; ascii char
  int 0x10   ; IO int

 resetdisk:
  mov ah, 0x00  ; reset function
  mov dl, 0x00  ; drive
  int 0x13   ; disk int
  jc resetdisk

 readdisk:
  mov bx, 0x8000  ; segment
  mov es, bx
  mov bx, 0x0000  ; offset

  mov ah, 0x02  ; read function
  mov al, 0x03  ; sectors
  mov ch, 0x00  ; cylinder
  mov cl, 0x02  ; sector
  mov dh, 0x00  ; head
  mov dl, 0x00  ; drive
  int 0x13   ; disk int
  jc readdisk
  jmp [es:bx]   ; buffer

 ;--------------------------------------------

 times 510 - ($ - $) db 0x00
 db 0x55, 0xAA

This is the code that should be (but isn't) loaded

 ;--------------------------------------------
 ; 'load.asm'
 ; loaded from 'boot.asm'

 [org 0x8000]
 [bits 16]

 ;--------------------------------------------

 main:
  mov ah, 0x0E  ; print function
  mov al, '.'   ; ascii char
  int 0x10   ; IO int

  jmp $    ; hang

Any help would be much appreciated.

Patrick

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

恏ㄋ傷疤忘ㄋ疼 2024-08-14 04:17:33

jmp [es:bx] 不会跳转到地址 es:bx。此命令执行近跳转到存储在 es:bx 的字中的地址。这就是为什么许多旧的汇编器让你将这种指令拼写为 jmp word ptr [es:bx] 甚至 jmp close ptr [es:bx];这样会发生什么就更清楚了。您可能想要的是远跳转到固定位置:

; jmp far 8000:0000
db 0eah
dw 00000h ; offset
dw 08000h ; segment

如果您确实想跳转到 es:bx,请使用 retf

push es
push bx
retf

jmp [es:bx] doesn't jump to the address es:bx. This command does a near jump to the address stored in the word at es:bx. This is why lots of older assemblers made you spell this kind of instruction as jmp word ptr [es:bx] or even jmp near ptr [es:bx]; it's clearer this way what is going to happen. What you probably want here is a far jump to a fixed location:

; jmp far 8000:0000
db 0eah
dw 00000h ; offset
dw 08000h ; segment

If you do want to jump to es:bx, use retf:

push es
push bx
retf
缘字诀 2024-08-14 04:17:33

我不确定你想用代码实现什么,但如果我理解正确的话,你想从磁盘读取几个扇区到位置 0x8000 然后执行该代码?

如果是这种情况,那么您将必须明确地调用/跳转到该特定位置。 BIOS 不会为您调用该代码。启动时,一旦 BIOS 初始化,它将把指令指针 IP 设置为地址 0x7c00。然后CPU将开始按顺序执行代码,因此如果没有对0x8000的JMP/CALL,它将不会执行0x8000处的代码,直到它执行了0x7c00到0x8000之间的每个内存地址等。

所以解决方案是有一个jmp或调用jc readdisk 之后的指令。

如果我的理解不正确,那么我深表歉意。希望这有帮助。

I am not sure what you are trying to achieve with the code, but if I understand it correctly, You want to read a few sectors from the disk into the location 0x8000 and then execute that code?

If that is the case, then you will have to explictly make a CALL/JUMP to that particular location. The BIOS will not call that code for you. On boot, once the BIOS is initialized, it will set the Instruction Pointer IP to the address 0x7c00. The cpu will then start to execute the code sequentially, so without a JMP/CALL to 0x8000 it wont execute the code at 0x8000 until it has executed every memory address inbetween 0x7c00 to 0x8000 etc.

So the solution would be to have a jmp or call instruction after your jc readdisk.

If my understanding is incorrect then I apologize. Hope this helps.

伪心 2024-08-14 04:17:33

INT13 的一个问题是磁头和磁道编号从 0 开始,但扇区编号由于某种原因从 1 开始。您可以检查扇区写入实用程序是否符合此编号方案。

问题:

  • 启动时您看到多少个点?
  • 软盘电机是否启动?

One gotcha with INT13 is that head and track numbers start at 0, but sector numbers for some reason start at 1. You might check that your sector-writing utility conforms to this numbering scheme.

Questions:

  • How many dots do you see when you boot?
  • Does the floppy motor kick on?
探春 2024-08-14 04:17:33

我不知道你是否使用软盘来启动你的操作系统,但是如果你使用的话,我建议你在 ORG 和 Bits 声明之后声明一些东西,看一下(它们非常重要):

JMP short main   ; Jump past disk description section
NOP              ; Pad out before disk description

; ------------------------------------------------------------------
; Disk description table, to make it a valid floppy
; Note: some of these values are hard-coded in the source!
; Values are those used by IBM for 1.44 MB, 3.5 diskette

OEMLabel            db "BERL OS"    ; Disk label - 8 chars
BytesPerSector      dw 512          ; Bytes per sector
SectorsPerCluster   db 1            ; Sectors per cluster
ReservedForBoot     dw 1            ; Reserved sectors for boot record
NumberOfFats        db 2            ; Number of copies of the FAT
RootDirEntries      dw 224          ; Number of entries in root dir
LogicalSectors      dw 2880         ; Number of logical sectors
MediumByte          db 0F0h         ; Medium descriptor byte
SectorsPerFat       dw 9            ; Sectors per FAT
SectorsPerTrack     dw 18           ; Sectors per track (36/cylinder)
Sides               dw 2            ; Number of sides/heads
HiddenSectors       dd 0            ; Number of hidden sectors
LargeSectors        dd 0            ; Number of LBA sectors
DriveNo             dw 0            ; Drive No: 0
Signature           db 41           ; Drive signature: 41 for floppy
VolumeID            dd 00000000h    ; Volume ID: any number
VolumeLabel         db "BERL OS"    ; Volume Label: any 11 chars
FileSystem          db "FAT12"      ; File system type: don't change!

; End of the disk description table
; ------------------------------------------------------------------

这是一个很好的方法想法把这个。

问候。

I don't know if you're using a floppy to boot your OS, but if you are using, i suggest you to declare some things after the ORG and Bits declaration, take a look(they are very important):

JMP short main   ; Jump past disk description section
NOP              ; Pad out before disk description

; ------------------------------------------------------------------
; Disk description table, to make it a valid floppy
; Note: some of these values are hard-coded in the source!
; Values are those used by IBM for 1.44 MB, 3.5 diskette

OEMLabel            db "BERL OS"    ; Disk label - 8 chars
BytesPerSector      dw 512          ; Bytes per sector
SectorsPerCluster   db 1            ; Sectors per cluster
ReservedForBoot     dw 1            ; Reserved sectors for boot record
NumberOfFats        db 2            ; Number of copies of the FAT
RootDirEntries      dw 224          ; Number of entries in root dir
LogicalSectors      dw 2880         ; Number of logical sectors
MediumByte          db 0F0h         ; Medium descriptor byte
SectorsPerFat       dw 9            ; Sectors per FAT
SectorsPerTrack     dw 18           ; Sectors per track (36/cylinder)
Sides               dw 2            ; Number of sides/heads
HiddenSectors       dd 0            ; Number of hidden sectors
LargeSectors        dd 0            ; Number of LBA sectors
DriveNo             dw 0            ; Drive No: 0
Signature           db 41           ; Drive signature: 41 for floppy
VolumeID            dd 00000000h    ; Volume ID: any number
VolumeLabel         db "BERL OS"    ; Volume Label: any 11 chars
FileSystem          db "FAT12"      ; File system type: don't change!

; End of the disk description table
; ------------------------------------------------------------------

It's a good idea to put this.

Regards.

悲喜皆因你 2024-08-14 04:17:33

我不确定为什么代码不起作用,因为我无法检查整个环境(磁盘、内存转储等)......但我可以说的是......代码是错误的。您正在加载第二个程序,不是在 0x8000 处(这就是使用 0rg 0x8000 对吧?),而是在 0x80000 处。

原因是,您以错误的方式使用段:偏移寻址,
地址 0x8000:0x0000 被解析为线性地址 0x80000,因为
段值左移 4 位,然后添加到偏移量中。

要解决此问题,您应该查看内存转储并查看是否
该程序也按照您的预期工作......要么那样,要么您正在加载
磁盘的错误扇区。

I'm not sure why the code doesn't work, since I can't check the the whole environment (disk, memory dump, etc)...but what I can say is...the code is wrong. You are loading the second program, not at 0x8000 (that was the point of using 0rg 0x8000 right?), but at 0x80000.

The reason being, you are using the segment:offset addressing in the wrong way,
the address 0x8000:0x0000 is resolved to the linear address 0x80000, since
the segment value is shifted left by 4 bits an then added to the offset.

To resolve this problem, you should take a look at a memory dump and see if
the program works as you expect it too....either that or you're loading the
wrong sectors of the disk.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文