加载引导加载程序的第二阶段和/或将控制权转移给它时出现问题 [英] Problems loading second stage of a bootloader and/or transferring control to it

查看:28
本文介绍了加载引导加载程序的第二阶段和/或将控制权转移给它时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的主引导记录代码:

;bit16;默认 16 位组织 0x7c00jmp 短启动没有bsOEM db "OS423 v.0.1" ;原始设备制造商字符串开始:;;CLSmov ah,06h ;函数06h(滚动屏幕)mov al,0 ;滚动所有行mov bh,0x0f ;属性(蓝底浅绿)mov ch,0 ;左上一行为零mov cl,0 ;左上列为零mov dh,24 ;左下一行是24mov dl,79 ;左下栏是79int 10h ;BIOS 中断 10h(视频服务);;打印欢迎信息mov ah,13h ;函数13h(显示字符串),仅限XT机mov al,1 ;写模式为零:光标停留在最后一个字符之后mov bh,0 ;使用视频页面为零mov bl,0x0f ;属性(蓝底浅绿)mov cx,mlen ;字符串长度mov dh,0 ;位置在第0行mov dl,0 ;和第0列lea bp,[msg] ;将字符串的偏移地址加载到BP中,es:bp;同 mov bp, msg10 小时;;将扇区加载到内存中5678h:1234hmov bx, 0x5678 ;分段地址mov es, bx ;移动分段地址到esmov bx,0x1234 ;基地址到bxmov ah, 02 ;函数读取扇区mov al, 01 ;要加载的扇区数mov ch, 00 ;要读取的轨道mov cl, 02 ;要读取的扇区mov dh, 00 ;读头mov dl, 00 ;驱动器号int 0x13 ;调用中断13jmp 0x5678:0x1234 ;跳转到内存地址整数 20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;msg: db '欢迎使用 Pradox OS 0.1!作者:何建松', 10, 13, '$'mlen equ $-msg填充时间 510-($-$$) db 0 ;使 MBR 为 512 字节bootSig db 0x55, 0xaa ;签名(可选)

我用于 nasm 编译并将二进制文件放入我的 .img 软盘的终端命令:

line1:定义一个名为boot.img的软盘,块大小512字节,共2880字节

line2:使用nasm编译器,将mbr.asm文件编译成二进制格式,存放在名为mbr.bin的文件中(这是我的主引导记录)

line3: 在 dt.bin 处将 dt.asm 编译成二进制

line4:将mbr.bin的内容放入boot.img,块大小512,共放入1块

line5:将dt.bin的内容放入boot.img,块大小512,物理扇区#2(逻辑扇区#1)

dd if=/dev/zero of=boot.img bs=512 count=2880nasm -f bin mbr.asm -o mbr.binnasm -f bin dt.asm -o dt.bindd if=mbr.bin of=boot.img bs=512 count=1 conv=notruncdd if=dt.bin of=boot.img bs=512 seek=1 count=1 conv=notrunc

dt.asm 中的代码:

[BITS 16] ;设置代码生成为16位模式ORG 0x5647:0x1234 ;设置地址从 579b4H 开始开始:;call cls ;调用例程清除屏幕;call dspmsg ;调用例程来显示消息通话日期呼叫 cvtmo致电 cvtday呼叫中心呼叫 cvtyear调用 dspdate通话时间呼叫 cvthrs呼叫 cvtmin呼叫 cvtsec呼叫 dsptimeint 20h ;停止操作(非常重要!!!)分类:mov ah,06h ;function 06h (滚动屏幕)mov al,0 ;滚动所有行mov bh,0x0f ;属性(蓝底白字)mov ch,0 ;左上一行为零mov cl,0 ;左上列为零mov dh,24 ;左下一行是24mov dl,79 ;左下栏是79int 10H ;BIOS 中断 10h(视频服务)回复dspmsg:mov ah,13h ;function 13h (显示字符串)mov al,1 ;写模式为零mov bh,0 ;使用视频页面为零mov bl,0x0a ;属性(亮蓝上亮白)mov cx,mlen2 ;字符长度mov dh,0 ;在第0行的位置mov dl,0 ;和第0列lea bp,[welcom] ;将字符串的偏移地址加载到BP10小时回复welcom: db 'jiangong Hes first Operating System :D',10,13,'$'mlen2 equ $-welcom;日期:;从系统获取日期mov ah,04h ;function 04h (获取 RTC 日期)int 1Ah ;BIOS 中断 1Ah(读实时时钟)回复;CH - 世纪;CL - 年;DH - 月;DL - 天简历:;将系统日期从 BCD 转换为 ASCIImov bh,dh ;复制月份(dh)的内容到bhshr bh,1shr bh,1shr bh,1shr bh,1添加 bh,30h ;添加 30h 转换为 asciimov [dtfld],bhmov bh,dh和 bh,0fh添加 bh,30hmov [dtfld + 1],bh回复生日:mov bh,dl ;将天(dl)的内容复制到bhshr bh,1shr bh,1shr bh,1shr bh,1添加 bh,30h ;添加 30h 转换为 asciimov [dtfld + 3],bhmov bh,dl和 bh,0fh添加 bh,30hmov [dtfld + 4],bh回复浓度:mov bh,ch ;复制世纪(ch)的内容到bhshr bh,1shr bh,1shr bh,1shr bh,1添加 bh,30h ;添加 30h 转换为 asciimov [dtfld + 6],bhmov bh,ch和 bh,0fh添加 bh,30hmov [dtfld + 7],bh回复年份:mov bh,cl ;复制年份(cl)的内容到bhshr bh,1shr bh,1shr bh,1shr bh,1添加 bh,30h ;添加 30h 转换为 asciimov [dtfld + 8],bhmov bh,cl和 bh,0fh添加 bh,30hmov [dtfld + 9],bh回复dtfld: db '00/00/0000'日期:;显示系统日期mov ah,13h ;function 13h (显示字符串)mov al,0 ;写模式为零mov bh,0 ;使用视频页面为零mov bl,0x0f ;属性mov cx,10 ;字符串长度为10mov dh,4 ;在第 4 行的位置mov dl,0 ;和第 28 列push ds ; 将 ds 寄存器放入堆栈pop es ;pop 到 es 寄存器lea bp,[dtfld] ;将字符串的偏移地址加载到BP中10小时回复时间:;从系统中获取时间移动啊,02h1Ah回复;CH - 小时;CL - 分钟;DH - 秒cvthrs:;将系统时间从BCD转换为ASCIImov bh,ch ;复制小时(ch)的内容到bhshr bh,1shr bh,1shr bh,1shr bh,1添加 bh,30h ;添加 30h 转换为 asciimov [tmfld],bhmov bh,ch和 bh,0fh添加 bh,30hmov [tmfld + 1],bh回复cvtmin:mov bh,cl ; 将分钟 (cl) 的内容复制到 bhshr bh,1shr bh,1shr bh,1shr bh,1添加 bh,30h ;添加 30h 转换为 asciimov [tmfld + 3],bhmov bh,cl和 bh,0fh添加 bh,30hmov [tmfld + 4],bh回复cvtsec:mov bh,dh ;复制秒(dh)的内容到bhshr bh,1shr bh,1shr bh,1shr bh,1添加 bh,30h ;添加 30h 转换为 asciimov [tmfld + 6],bhmov bh,dh和 bh,0fh添加 bh,30hmov [tmfld + 7],bh回复tmfld: db '00:00:00'时间:;显示系统时间mov ah,13h ;function 13h (显示字符串)mov al,0 ;写模式为零mov bh,0 ;使用视频页面为零mov bl,0x0f;属性mov cx,8 ;字符串长度为8mov dh,5 ; 位置在第 5 行mov dl,0;和第0列push ds ; 将 ds 寄存器放入堆栈pop es ;pop 到 es 寄存器lea bp,[tmfld] ;将字符串的偏移地址加载到BP中10小时回复20小时

我的测试环境是 dosbox,我可以在屏幕上成功显示欢迎消息,但无法将另一个扇区加载到内存中,从 0x5647:0x1234 开始谢谢

解决方案

由于其他答案中未涵盖许多问题,我将提供一个新答案.

我建议在其他 Stackoverflow 答案中查看我的一般引导加载程序提示.特别是前几个技巧在这里适用:

<块引用>

  1. 当 BIOS 跳转到您的代码时,您不能依赖 CSDSESSS,SP 寄存器具有有效值或预期值.当您的引导加载程序启动时,它们应该被适当地设置.您只能保证您的引导加载程序将从物理地址 0x00007c00 加载并运行,并且引导驱动器编号已加载到 DL 寄存器中.

  2. lodsbmovsb 等使用的方向标志可以设置或清除.如果方向标志设置不当,SI/DI 寄存器可能会调整到错误的方向.使用 STD/CLD 将其设置为您希望的方向(CLD=forward/STD=backwards).在这种情况下,代码假定向前移动,因此应使用 CLD.可以在 指令集参考

    中找到更多相关信息
  3. 当跳转到一个内核时,通常一个好主意是 FAR JMP 到它,以便它正确地将 CS:IP 设置为预期值.这可以避免内核代码可能在同一段内执行absolute near JMPsCALLs 的问题.

在您的代码中,您的引导加载程序应该在 SS:SP 中设置一个堆栈指针.将它放在引导加载程序正下方是合理的 0x0000:0x7c00.您应该在销毁DL 寄存器之前保存它,因为它包含引导驱动器编号.您可以在开始时将其压入堆栈,并在设置访问的磁盘相关例程时将其恢复 int 13h.您不应假设 ESDS(特别是 DS)的值设置为 0.因为您使用的 ORG 为 0x7c00这些段需要 0x0000.(0x0000<<4)+0x7c00 = 物理地址 0x07c00.

要解决这些问题,您可以在 start 标签后添加这些行:

开始:mov [bootdrv],dl;将通过DL传入的启动盘保存到bootloaderxor ax,ax ; 因为我们使用 ORG 0x7c00,所以将 ES 和 DS 设置为零移动,斧头mov ds,axmov ss,ax ;将 SS:SP 设置为引导加载程序下方的 0x0000:0x7c00mov sp,0x7c00cld ;设置方向标志向前

您需要在拥有 msg

后添加一个 bootdrv 变量

bootdrv: db 0

在使用 int 13h 磁盘读取功能之前,您现在可以在发出中断之前使用 bootdrv 中的值并将其放入 DL称呼.这一行应该被替换:

mov dl, 00 ;驱动器号

与:

mov dl,[bootdrv];获取bootloader启动时保存的启动盘


jmp 0x5678:0x1234 之后,您的引导加载程序中有 int 20.我相信你的意思是 int 20h.JMP 永远不会返回,所以在它什么都不做之后放置代码.但是,int 20h 是 DOS 中断,只有在 MS-DOS 系统从磁盘加载到内存后才可用.当然,您的磁盘上没有 MS-DOS.在引导加载程序(裸机)环境中,根本不要使用 DOS 中断.


dt.asm 中你有一些问题.您FAR JMP 到 0x5678:0x1234 处新加载的代码.在这样做时 CS 被设置为 0x5678.您需要手动设置ESDS,您可以通过将CS 中的值复制到DS 来实现> 和 ES.您还需要设置适当的 ORG.在这种情况下,原点是从段的开头 (0x5678) 开始的 0x1234,因此您必须使用 org 0x1234 .dt.asm 的顶部可以修改为:

BITS 16 ;设置代码生成为16位模式ORG 0x1234 ;设置原点为0x1234mov ax, cs ;复制 CS 到 DS 和 ES;或者可以使用 mov ax, 0x5678mov ds, ax移动,斧头开始:


前面讨论的 int 20h 问题是 dt.asm 中的问题.删除它的所有出现.相反,您可以将处理器置于无限循环中.dt.asm 中执行的最后一段代码是在 call dsptime 返回之后.在 CALL 之后,您可以使用以下内容进行无限循环:

 jmp $

一个更可取的可以减少处理能力的无限循环是使用 CLI,使用 HLT 指令,然后为了安全措施,如果 HLT 返回 JMP 并再次执行 HLT(如果存在 NMI 非-可屏蔽中断).HLT 等待下一个中断发生.这是您经常看到的:

 cli结束循环:高jmp 结束循环


其他观察

它出现在您将参数发布到 的代码的第一个版本中INT 13h/AH=2 磁盘读取功能不正确.扇区编号从 1 开始,磁头和柱面从零开始.中断信息的最佳来源是 Ralph Brown 的中断列表,其中涵盖了 BIOS 和 MS-DOS 中断.如果您需要有关中断参数的信息,这是一个很好的参考.


我建议使用 BOCHS 来调试引导加载程序.它有一个命令行调试器,可以理解实模式寻址,可用于在指令执行时观察指令、设置断点、显示寄存器、检查内存等.

my code for master boot record:

;bit16                  ; 16bit by default
    org 0x7c00
    jmp short start
    nop
bsOEM   db "OS423 v.0.1"               ; OEM String

start:


;;cls
    mov ah,06h      ;Function 06h (scroll screen)
    mov al,0        ;Scroll all lines
    mov bh,0x0f     ;Attribute (lightgreen on blue) 
    mov ch,0        ;Upper left row is zero
    mov cl,0        ;Upper left column is zero
    mov dh,24       ;Lower left row is 24
    mov dl,79       ;Lower left column is 79
    int 10h         ;BIOS Interrupt 10h (video services)

;;print welcome msg
    mov ah,13h      ;Function 13h (display string), XT machine only
    mov al,1        ;Write mode is zero: cursor stay after last char
    mov bh,0        ;Use video page of zero
    mov bl,0x0f     ;Attribute (lightgreen on blue)
    mov cx,mlen     ;Character string length
    mov dh,0        ;Position on row 0
    mov dl,0        ;And column 0
    lea bp,[msg]    ;Load the offset address of string into BP, es:bp
                    ;Same as mov bp, msg 
    int 10h

;;load sector into memory & 5678h:1234h
    mov bx, 0x5678  ;segmented address
    mov es, bx      ;move segemented address to es
    mov bx,0x1234       ;base address to bx

    mov ah, 02      ;function read sectors
    mov al, 01      ;# of sectors to load
    mov ch, 00      ;track to read
    mov cl, 02      ;sector to read
    mov dh, 00      ;head to read
    mov dl, 00          ;drive number

    int 0x13            ;call interrupt 13 

    jmp 0x5678:0x1234       ;jump to memory address 


    int 20


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;variables;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

msg:  db 'Welcome to Pradox OS 0.1! Authored by Jiansong he', 10, 13, '$' 
mlen equ $-msg

padding times 510-($-$$) db 0       ;to make MBR 512 bytes
bootSig db 0x55, 0xaa       ;signature (optional)

my terminal command for nasm compiling and puting the binary files into my .img floppy disk:

line1: define a floppy dick named boot.img, block size 512 byte, in total of 2880 byte

line2: use nasm compiler, compile mbr.asm file into binary format, store it at file named mbr.bin(which is my master boot record)

line3: compile dt.asm into binary at dt.bin

line4: put mbr.bin's content into boot.img, block size 512, put total 1 block

line5: put dt.bin's content into boot.img, block size 512, at physical sector #2(logical sector #1)

dd if=/dev/zero of=boot.img bs=512 count=2880 

nasm -f bin mbr.asm -o mbr.bin

nasm -f bin dt.asm -o dt.bin 

dd if=mbr.bin of=boot.img bs=512 count=1 conv=notrunc

dd if=dt.bin of=boot.img bs=512 seek=1 count=1 conv=notrunc 

code in dt.asm:

[BITS 16]               ;Set code generation to 16 bit mode

ORG 0x5647:0x1234       ;set addressing to begin at 579b4H

startdt:
  ;call cls ;call routine to clear screen
  ;call dspmsg  ;call routine to display message

  call date
  call cvtmo
  call cvtday
  call cvtcent
  call cvtyear
  call dspdate

  call time
  call cvthrs
  call cvtmin
  call cvtsec
  call dsptime

  int 20h ;halt operation (VERY IMPORTANT!!!)


cls:             
  mov ah,06h    ;function 06h (Scroll Screen)
  mov al,0  ;scroll all lines
  mov bh,0x0f   ;Attribute (bright white on blue)
  mov ch,0  ;Upper left row is zero
  mov cl,0  ;Upper left column is zero
  mov dh,24 ;Lower left row is 24
  mov dl,79 ;Lower left column is 79
  int 10H   ;BIOS Interrupt 10h (video services)
  ret


dspmsg: 
  mov ah,13h    ;function 13h (Display String)
  mov al,1  ;Write mode is zero
  mov bh,0  ;Use video page of zero
  mov bl,0x0a   ;Attribute (bright white on bright blue)
  mov cx,mlen2  ;Character length
  mov dh,0  ;position on row 0
  mov dl,0  ;and column 0
  lea bp,[welcom]   ;load the offset address of string into BP

  int 10H
  ret

welcom: db 'jiansong Hes first Operating System :D',10,13,'$'
mlen2 equ $-welcom;

date:
;Get date from the system
mov ah,04h   ;function 04h (get RTC date)
int 1Ah     ;BIOS Interrupt 1Ah (Read Real Time Clock)
ret

;CH - Century
;CL - Year
;DH - Month
;DL - Day

cvtmo:
;Converts the system date from BCD to ASCII
mov bh,dh ;copy contents of month (dh) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [dtfld],bh
mov bh,dh
and bh,0fh
add bh,30h
mov [dtfld + 1],bh
ret

cvtday:
mov bh,dl ;copy contents of day (dl) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [dtfld + 3],bh
mov bh,dl
and bh,0fh
add bh,30h
mov [dtfld + 4],bh
ret

cvtcent:
mov bh,ch ;copy contents of century (ch) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [dtfld + 6],bh
mov bh,ch
and bh,0fh
add bh,30h
mov [dtfld + 7],bh
ret

cvtyear:
mov bh,cl ;copy contents of year (cl) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [dtfld + 8],bh
mov bh,cl
and bh,0fh
add bh,30h
mov [dtfld + 9],bh
ret

dtfld: db '00/00/0000'

dspdate:
;Display the system date
mov ah,13h ;function 13h (Display String)
mov al,0 ;Write mode is zero
mov bh,0 ;Use video page of zero
mov bl,0x0f ;Attribute
mov cx,10 ;Character string is 10 long
mov dh,4 ;position on row 4
mov dl,0 ;and column 28
push ds ;put ds register on stack
pop es ;pop it into es register
lea bp,[dtfld] ;load the offset address of string into BP
int 10H
ret

time:
;Get time from the system
mov ah,02h
int 1Ah
ret

;CH - Hours
;CL - Minutes
;DH - Seconds

cvthrs:
;Converts the system time from BCD to ASCII
mov bh,ch ;copy contents of hours (ch) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [tmfld],bh
mov bh,ch
and bh,0fh
add bh,30h
mov [tmfld + 1],bh
ret

cvtmin:
mov bh,cl ;copy contents of minutes (cl) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [tmfld + 3],bh
mov bh,cl
and bh,0fh
add bh,30h
mov [tmfld + 4],bh
ret

cvtsec:
mov bh,dh ;copy contents of seconds (dh) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [tmfld + 6],bh
mov bh,dh
and bh,0fh
add bh,30h
mov [tmfld + 7],bh
ret

tmfld: db '00:00:00'

dsptime:
;Display the system time
mov ah,13h ;function 13h (Display String)
mov al,0 ;Write mode is zero
mov bh,0 ;Use video page of zero
mov bl,0x0f;Attribute
mov cx,8 ;Character string is 8 long
mov dh,5 ;position on row 5
mov dl,0;and column 0
push ds ;put ds register on stack
pop es ;pop it into es register
lea bp,[tmfld] ;load the offset address of string into BP
int 10H
ret

int 20H

my testing environment is dosbox, I can successfully display the welcome message on screen but failed to load another sector into memory starting at 0x5647:0x1234 thanks

解决方案

Since there are a number of issues not covered in the other answer, I'll provide a new answer.

I recommend looking at my General Bootloader Tips in this other Stackoverflow answer. In particular the first few tips apply here:

  1. When the BIOS jumps to your code you can't rely on CS,DS,ES,SS,SP registers having valid or expected values. They should be set up appropriately when your bootloader starts. You can only be guaranteed that your bootloader will be loaded and run from physical address 0x00007c00 and that the boot drive number is loaded into the DL register.

  2. The direction flag used by lodsb, movsb etc could be either set or cleared. If the direction flag is set improperly SI/DI registers may be adjusted in the wrong direction. Use STD/CLD to set it to the direction you wish (CLD=forward/STD=backwards). In this case the code assumes forward movement so one should use CLD. More on this can be found in an instruction set reference

  3. When jumping to a kernel it is generally a good idea to FAR JMP to it so that it properly sets CS:IP to expected values. This can avoid problems with kernel code that may do absolute near JMPs and CALLs within the same segment.

In your code your bootloader should set up a stack pointer in SS:SP. Placing it just below the bootloader is reasonable at 0x0000:0x7c00. You should save DL register before destroying it because it contains the boot drive number. You could push it on the stack at the start and restore it when you set up the disk related routines accessed int 13h. You shouldn't assume that ES or DS (DS in particular) are set to the value of 0. Since you use an ORG of 0x7c00 the segments need 0x0000. (0x0000<<4)+0x7c00 = physical address 0x07c00.

To resolve these issues you could add these lines after the start label:

start:
    mov [bootdrv],dl;Save the boot drive passed in via DL to the bootloader
    xor ax,ax       ;Set ES and DS to zero since we use ORG 0x7c00
    mov es,ax
    mov ds,ax
    mov ss,ax       ;Set SS:SP to 0x0000:0x7c00 below bootloader
    mov sp,0x7c00
    cld             ;Set direction flag forward

You'll need to add a bootdrv variable after you have msg

bootdrv: db 0

Before you use the int 13h disk read feature you can now use the value in bootdrv and place it into DL before issuing the interrupt call. This line should be replaced:

mov dl, 00      ;drive number

With:

mov dl,[bootdrv];Get the boot drive saved at start of bootloader


You have int 20 in your bootloader after the jmp 0x5678:0x1234. I believe you meant int 20h. The JMP will never return so placing code after it will do nothing. However, int 20h is a DOS interrupt that is only available after MS-DOS system is loaded from disk into memory. You have no MS-DOS on your disk of course. In a bootloader (bare metal) environment just don't use DOS interrupts at all.


In dt.asm you have some issues. You FAR JMP to the newly loaded code at 0x5678:0x1234. In doing so CS was set to 0x5678. You'll need to manually set ES and DS, You can do this by copying the value in CS to DS and ES. You also need to set the appropriate ORG. In this case the origin point is 0x1234 from the beginning of the segment (0x5678) so you must use org 0x1234 . The top of dt.asm could be modified to look like:

BITS 16               ;Set code generation to 16 bit mode

ORG 0x1234            ;set origin point to 0x1234
mov ax, cs            ;copy CS to DS and ES
                      ;alternatively could have used mov ax, 0x5678
mov ds, ax
mov es, ax

startdt:


The issue with int 20h discussed previously is an issue in dt.asm. Remove all occurrences of it. Instead you can put the processor in an infinite loop. The last of your code in dt.asm that is executed is after call dsptime returns. After that CALL you can put an infinite loop with something like:

    jmp $

A more preferable infinite loop that can take less processing power is to turn off the interrupts using CLI, use a HLT instruction and then for safe measure if HLT returns JMP back and do HLT again (Could happen if there is an NMI Non-Maskable Interrupt). HLT waits until the next interrupt occurs. This is what you'll often see instead:

    cli
endloop:
    hlt
    jmp endloop


Other Observations

It appears in the first version of the code you posted the parameters to INT 13h/AH=2 disk read function were incorrect. Sector numbers start at 1 and heads and cylinders are zero based. The best source of interrupt information is Ralph Brown's Interrupt List which covers both BIOS and MS-DOS interrupts. If you need information on the parameters of the interrupts it is an excellent reference.


I'd recommend BOCHS for debugging bootloaders. It has a command line debugger that understands real mode addressing and can be used to watch instructions as they are executed,set breakpoints, display registers, examine memory etc.

这篇关于加载引导加载程序的第二阶段和/或将控制权转移给它时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆