Assembly 如何使用NASM调用位于后两个扇区的代码?
也许我很愚蠢,不知道什么,但我认为我做得对。我有两个文件,一个是Assembly 如何使用NASM调用位于后两个扇区的代码?,assembly,nasm,x86-16,bootloader,Assembly,Nasm,X86 16,Bootloader,也许我很愚蠢,不知道什么,但我认为我做得对。我有两个文件,一个是boot.asm,第二个是code.asm。在boot.asm中,我只启用视频模式,用蓝色填充屏幕,并尝试加载位于两秒扇区的代码,但当我尝试时,什么都不会发生,也无法找出我做错了什么,可能是我读错了或code.asm编码错误或boot.asm编码错误。为什么我不能调用存储在两秒扇区中的代码来完成它们 为了获得更多信息,我将从MBR加载这段代码,我想在两个第二个扇区调用代码,因为我不能将它们全部放在一个扇区中,所以我提出这个问题 bo
boot.asm
,第二个是code.asm
。在boot.asm
中,我只启用视频模式,用蓝色填充屏幕,并尝试加载位于两秒扇区的代码,但当我尝试时,什么都不会发生,也无法找出我做错了什么,可能是我读错了或code.asm
编码错误或boot.asm
编码错误。为什么我不能调用存储在两秒扇区中的代码来完成它们
为了获得更多信息,我将从MBR加载这段代码,我想在两个第二个扇区调用代码,因为我不能将它们全部放在一个扇区中,所以我提出这个问题
boot.asm
;bootloader
bits 16
org 0x7c00
;Here i try to load code located at second two sectors
Load_Code:
;---Setup segments
xor ax, ax ; AX=0
mov ds, ax ; DS=ES=0 because we use an org of 0x7c00 - Segment<<4+offset = 0x0000<<4+0x7c00 = 0x07c00
mov ax, es
mov ax, ss
mov sp, 0x7c00 ; SS:SP= 0x0000:0x7c00 stack just below bootloader
;---Read 2 sectors
mov bx, buffer ; ES: BX must point to the buffer
mov dh,0 ; head number
mov ch,0 ; track number
mov cl,2 ; sector number
mov al,2 ; number of sectors to read
mov ah,2 ; read function number
int 13h
;Graphics mode
Set_Video:
mov ax, 12h ; Graphics mode (640x480x16)
int 10h ; BIOS draw function
mov ah, 06h ; Scroll up function
xor al, al ; Clear entire screen
xor cx, cx ; Upper left corner CH=row, CL=column
mov dx, 3FFFh ; fill whole screen
mov bh, 11h ; blue background
int 10h ; BIOS draw function
call buffer
;Endless loop
.endloop:
hlt
jmp .endloop
;Fake MBR signature
MBR_Signature:
times 510 - ($ - $$) db 0
dw 0xAA55
buffer:
问题最有可能的原因是,清除屏幕时,您正在重击
dl
的内容
当BIOS加载引导扇区并调用它时,它会将驱动器号放入dl
。您必须保留此值,以便在以后尝试将后续扇区加载到内存时使用。由于未能执行此操作,当您尝试读取驱动器时,BIOS将尝试从(可能)不存在的设备读取
你怎么画12小时的屏幕真奇怪 此屏幕有80列30行,因此右下角位于(79,29)。
您还忘记指定左上角,即(0,0)。您的引导加载程序在启动时不应依赖于
CX
的零值
mov ah, 0x07 ; function to call with interrupt
mov bh, 0x01 ; blue background
xor cx, cx ; (0,0) <-----
mov dx, 0x1D4F ; (79,29) <-----
int 0x10 ; BIOS draw function
mov-ah,0x07;函数调用中断
mov-bh,0x01;蓝色背景
异或cx,cx;(0,0)乍一看没有明显的错误。使用调试器。另外,添加错误处理。此外,添加一些结尾,如果您想解决加载问题,请不要弄乱图形。我已经这样做了,并且它似乎按照预期工作。buffer
不会以ret
结束,以便在调用后返回指针。
还注意到,您的所有段寄存器设置都是反向的mov ax,ds
应该是mov ds,ax
同样的事情也适用于es和ss。当您执行mov dx,0x3fff
时,您还可以删除具有驱动器号的DL。您可以在修改dx之前推送
dx',然后在int 10h
之后弹出dx
,或者暂时将dx移到另一个寄存器中并将其移回。无论哪种方式,您都需要在修改DX之前保存它,以便磁盘读取在以后的中具有正确的引导驱动器号DL@MichaelPetch看起来我的第一眼并没有那么彻底:)是的,你是对的,但我如何在不破坏dl
内容的情况下清除屏幕?我不能先加载扇区然后清除屏幕,我必须先清理屏幕,不要问为什么。最简单的方法是先定义堆栈并将其推送到那里,或者定义DS所在的位置并将其存储在代码段中的某个位置。:)现在我的堆栈是128kb大,我必须用32kb加载它4次,当我在开始时定义它时,我以后不能运行它,因为16位模式限制是64k,所以它只完成50%。我不知道如何解决它。听起来你好像又在问其他问题了。:)我不清楚你为什么认为你需要这么大的堆栈…因为我在这个大堆栈中存储了逐像素绘制图像的代码。我只对错误方向上的分段操作负责。我意识到段设置代码看起来很熟悉。它来自我上周写的答案:。我是一个谁写他们向后和人们使用的代码。我已经纠正了那个答案中的错误。直到不久前我才意识到这一点。
xor ax, ax ; AX=0
mov ds, ax ; DS=ES=0 because we use an org of 0x7c00 - Segment<<4+offset = 0x0000<<4+0x7c00 = 0x07c00
mov ax, es
mov ax, ss
mov sp, 0x7c00
xor ax, ax
mov ds, ax
mov es, ax <---
mov ss, ax <---
mov sp, 0x7c00
mov ah, 0x07 ; function to call with interrupt
mov bh, 0x01 ; blue background
mov dx, 0x3FFF ; fill whole screen
int 0x10 ; BIOS draw function
mov ah, 0x07 ; function to call with interrupt
mov bh, 0x01 ; blue background
xor cx, cx ; (0,0) <-----
mov dx, 0x1D4F ; (79,29) <-----
int 0x10 ; BIOS draw function