11

我已经坚持了好几个星期了,不知道我哪里出错了,因为 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

任何帮助将不胜感激。

帕特里克

4

5 回答 5

7

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

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

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

push es
push bx
retf
于 2009-10-13T10:23:08.773 回答
2

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

问题:

  • 开机时看到多少个点?
  • 软盘电机是否启动?
于 2009-10-13T10:16:48.910 回答
2

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

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

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

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

于 2009-10-11T18:34:04.470 回答
1

我不知道你是不是用软盘来启动你的操作系统,但是如果你正在使用,我建议你在 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
; ------------------------------------------------------------------

放这个是个好主意。

问候。

于 2009-10-12T11:34:49.453 回答
0

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

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

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

于 2011-04-30T16:53:46.440 回答