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