我已经坚持了好几个星期,并且不知道我哪里出错了,因为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
任何帮助将不胜感激。
帕特里克
答案 0 :(得分:7)
jmp [es:bx]
不会跳转到地址es:bx
。此命令几乎跳转到存储在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
答案 1 :(得分:2)
我不确定您要使用代码实现什么,但如果我理解正确,您想从磁盘读取几个扇区到0x8000位置然后执行该代码?
如果是这种情况,那么你必须明确地向该特定位置发出CALL / JUMP。 BIOS不会为您调用该代码。在启动时,初始化BIOS后,它会将指令指针IP设置为地址0x7c00。然后cpu将开始按顺序执行代码,因此如果没有JMP / CALL到0x8000,它将不会执行0x8000处的代码,直到它执行0x7c00到0x8000之间的每个内存地址等。
所以解决方案是在你的jc readdisk之后有一个jmp或call指令。
如果我的理解不正确,那么我道歉。希望这会有所帮助。
答案 2 :(得分:2)
INT13的一个问题是磁头和磁道编号从0开始,但扇区编号由于某种原因从1开始。您可能会检查您的扇区写入实用程序是否符合此编号方案。
问题:
答案 3 :(得分: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
; ------------------------------------------------------------------
把这个放在一边是个好主意。
问候。
答案 4 :(得分:0)
我不确定为什么代码不起作用,因为我无法检查整个环境(磁盘,内存转储等)......但我能说的是......代码错误。您正在加载第二个程序,而不是0x8000
(这是使用0rg 0x8000
对吗?),而是0x80000
。
原因是,您正在使用段:偏错寻址方式错误,
地址0x8000:0x0000
已解析为线性地址0x80000
,因为
段值向左移4位,然后加到偏移量。
要解决此问题,您应该查看内存转储并查看是否 程序按你期望的那样工作....或者你正在加载 错误的磁盘扇区。