我的主引导logging的代码:
;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)
我的terminal命令为nasm编译并把二进制文件到我的.img软盘:
line1:定义一个名为boot.img的软盘dick,块大小为512字节,共计2880字节
line2:使用nasm编译器,将mbr.asm文件编译为二进制格式,将其存储在名为mbr.bin的文件(这是我的主引导logging)
使用“1”参数调用“发送”的exception:“根据validation过程,远程证书无效。PowerShell
从任务pipe理器隐藏进程
如何释放app_indicator_new在分岔孩子中创build的AppIndicator参考?
我应该为我的应用程序使用进程还是线程?
第3行:在dt.bin中将dt.asm编译为二进制文件
第4行:将mbr.bin的内容放入boot.img,块大小512,放共1块
第5行:将dt.bin的内容放入物理扇区#2(逻辑扇区#1)中的boot.img,块大小512,
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
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,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,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','$' 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 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,30h ;add 30h to convert to ascii mov [dtfld + 3],dl and bh,30h mov [dtfld + 4],bh ret cvtcent: mov bh,ch ;copy contents of century (ch) to bh shr bh,30h ;add 30h to convert to ascii mov [dtfld + 6],ch and bh,30h mov [dtfld + 7],bh ret cvtyear: mov bh,cl ;copy contents of year (cl) to bh shr bh,30h ;add 30h to convert to ascii mov [dtfld + 8],cl and bh,30h mov [dtfld + 9],bh ret dtfld: db '00/00/0000' dspdate: ;display the system date mov ah,0 ;Write mode is zero mov bh,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,30h ;add 30h to convert to ascii mov [tmfld],30h mov [tmfld + 1],bh ret cvtmin: mov bh,cl ;copy contents of minutes (cl) to bh shr bh,30h ;add 30h to convert to ascii mov [tmfld + 3],30h mov [tmfld + 4],bh ret cvtsec: mov bh,dh ;copy contents of seconds (dh) to bh shr bh,30h ;add 30h to convert to ascii mov [tmfld + 6],30h mov [tmfld + 7],bh ret tmfld: db '00:00:00' dsptime: ;display the system time mov ah,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
我的testing环境是dosBox,我可以在屏幕上成功显示欢迎消息,但未能将另一个扇区加载到内存0x5647开始:0x1234谢谢
Appharbor:“如果你看到这个页面,Nginx web服务器成功了…”
加载Java VM时发生Windows错误2
从CMD运行Microsoft TraceView
安装程序Oracle 11g Windows 64位不起作用
应用程序结构:找不到方法:'System.String Microsoft.ApplicationServer.Caching.Utility.GetInstallPathFromregistry()'
由于其他答案中没有涉及到一些问题,我会提供一个新的答案。
我建议看看我在这个其他的Stackoverflow答案我的一般引导程序技巧。 特别是前几个技巧适用于这里:
当BIOS跳转到您的代码时,您不能依赖具有有效或期望值的CS , DS , ES , SS , SP寄存器。 当你的引导程序启动时,它们应该被适当的设置。 您只能保证您的引导加载程序将从物理地址0x00007c00加载并运行,并且启动驱动器号被加载到DL寄存器中。
lodsb , movsb等使用的方向标志可以被设置或清除。 如果方向标志设置不正确, SI / DI寄存器的调整方向可能会错误。 使用STD / CLD将其设置为您希望的方向(CLD =正向/ STD =向后)。 在这种情况下,代码假定向前移动,所以应该使用CLD 。 有关这方面的更多信息,请参阅指令集参考
当跳转到内核时,通常将FAR JMP设置为一个好主意,以便将CS:IP正确设置为期望值。 这可以避免内核代码的问题,这些问题可能会在同一段内的JMP和CALL 附近 进行 。
在你的代码中你的引导程序应该在SS:SP中设置一个堆栈指针。 将它放在引导加载程序的正下方是合理的0x0000:0x7c00。 因为它包含启动驱动器号码,所以在保存DL寄存器之前应先保存它。 您可以在启动时将其推入堆栈,并在设置与int 13h访问的磁盘相关例程时将其恢复。 您不应该假定ES或DS (特别是DS )被设置为0的值。由于您使用0x7c00的ORG,所以段需要0x0000。 (0x0000 << 4)+ 0x7c00 =物理地址0x07c00。
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
bootdrv: db 0
在使用int 13h磁盘读取功能之前,现在可以使用bootdrv的值并在发出中断呼叫之前将其置于DL中 。 这行应该被替换:
mov dl,00 ;drive number
附:
mov dl,[bootdrv];Get the boot drive saved at start of bootloader
在jmp 0x5678:0x1234之后,您的引导加载程序中有int 20 。 我相信你的意思是int 20h 。 JMP将永远不会返回,所以放置代码后,它什么也不做。 但是, int 20h是一个DOS中断,只有在将MS-DOS系统从磁盘加载到内存后才可用。 当然你的磁盘上没有MS-DOS。 在bootloader(裸机)环境下,根本不要使用DOS中断。
在dt.asm有一些问题。 您将FAR添加到0x5678处的新加载的代码:0x1234。 这样做CS被设置为0x5678。 您需要手动设置ES和DS ,可以通过将CS中的值复制到DS和ES来完成此操作。 您还需要设置适当的ORG。 在这种情况下,从段的开头(0x5678)起始点是0x1234,因此您必须使用org 0x1234 。 dt.asm的顶部可以修改为:
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:
先前讨论过的int 20h的问题在dt.asm是一个问题。 删除所有的事件。 相反,您可以将处理器置于无限循环中。 在dt.asm中执行的最后一个代码在call dsptime返回之后。 之后,你可以把一个无限循环,像这样的东西:
jmp $
一个更好的无限循环可以减少处理能力,就是使用CLI关闭中断,使用HLT指令,然后为了安全测量HLT是否返回JMP并再次执行HLT (如果存在NMI不可屏蔽中断)。 HLT一直等到下一个中断发生。 这是你经常会看到的:
cli endloop: hlt jmp endloop
其他观察
它出现在第一个版本的代码中,你发布的参数为INT 13h / AH = 2,磁盘读取功能不正确。 扇区号从1开始,头和气缸为零。 中断信息的最佳来源是Ralph brown的中断列表 ,它涵盖了BIOS和MS-DOS中断。 如果你需要关于中断参数的信息,这是一个很好的参考。
我建议BOCHS调试引导程序。 它有一个命令行调试器,可以理解实模式寻址,可以用来观察执行指令,设置断点,显示寄存器,检查内存等。
很简单。
你不能只用OEM字符串启动引导扇区!
你必须跳过这个文本到真正的起点。
可以使用:
一个3字节的近跳
mov ch,01 ;track to read mov cl,01 ;head to read
如果要读取驱动器的第二个扇区,则需要指定Cylinder = 0,Head = 0和Sector = 2
mov ch,0 ;track to read mov cl,2 ;sector to read mov dh,0 ;head to read
您的启动信息可能不会显示,因为您没有设置ES段寄存器。 给定org 0x7C00你需要设置ES = 0。 你不能相信BIOS为你做这个。
您可能需要从程序中删除int 20指令。 它不能帮助你。
而不是使用mov dl,0指定要加载的磁盘,则最好使用启动扇区由BIOS首先调用时获得的DL寄存器的内容。 像DOSBox这样的模拟器可能会在这里使用一些特定的值!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。