Assembly BIOS读扇区

Assembly BIOS读扇区,assembly,x86,nasm,boot,bios,Assembly,X86,Nasm,Boot,Bios,为了学习,我已经考虑过制作一个小型操作系统,现在正在使用引导加载程序。我希望能够使用int0x13从软盘驱动器读取扇区,将它们放入内存,然后跳转到该代码。以下是我到目前为止的情况: org 0x7c00 bits 16 main: call setup_segments mov ah, 2 ; function mov al, 1 ; num of sectors mov ch, 1 ; cylinder mov cl,

为了学习,我已经考虑过制作一个小型操作系统,现在正在使用引导加载程序。我希望能够使用
int0x13
从软盘驱动器读取扇区,将它们放入内存,然后跳转到该代码。以下是我到目前为止的情况:

org 0x7c00
bits 16

main:
    call setup_segments

    mov ah, 2      ; function
    mov al, 1      ; num of sectors
    mov ch, 1      ; cylinder
    mov cl, 2      ; sector
    mov dh, 0      ; head
    mov dl, 0      ; drive
    mov bx, 0x1000 ;
    mov es, bx     ; dest (segment)
    mov bx, 0      ; dest (offset)
    int 0x13       ; BIOS Drive Interrupt

    jmp 0x1000:0   ; jump to loaded code

times 510 - ($-$$) db 0 ; fluff up program to 510 B
dw 0xAA55               ; boot loader signature




LoadTarget: ; Print Message, Get Key Press, Reboot

jmp new_main

Greeting: db "Hello, welcome to the bestest bootloader there ever was!", 0
Prompt:   db "Press any key to reboot...", 0

Println:
    lodsb ; al <-- [ds:si], si++

    or al, al    ; needed for jump ?
    jz PrintNwl  ; if null is found print '\r\n'
    mov ah, 0x0e ; function
    mov bh, 0    ; page number ?
    mov bl, 7    ; text attribute ?
    int 0x10     ; BIOS Interrupt
    jmp Println

PrintNwl: ; print \r\n
    ; print \r
    mov ah, 0x0e ; function
    mov al, 13   ; char (carriage return)
    mov bh, 0    ; page number ?
    mov bl, 7    ; text attribute ?
    int 0x10

    ; print \n
    mov ah, 0x0e ; function
    mov al, 20   ; char (line feed)
    mov bh, 0    ; page number ?
    mov bl, 7    ; text attribute ?
    int 0x10

    ret          ; return

GetKeyPress:
    mov si, Prompt ; load prompt
    call Println   ; print prompt

    xor ah, ah     ; clear ah
    int 0x16       ; BIOS Keyboard Service

    ret            ; return

setup_segments:
    cli ;Clear interrupts
    ;Setup stack segments
    mov ax,cs
    mov ds,ax
    mov es,ax
    mov ss,ax
    sti ;Enable interrupts

    ret

new_main:
    call setup_segments

    mov si, Greeting ; load greeting
    call Println     ; print greeting

    call GetKeyPress ; wait for key press

    jmp 0xffff:0     ; jump to reboot address

times 1024 - ($-$$) db 0 ; fluff up sector
org 0x7c00
第16位
主要内容:
呼叫设置\u段
mov-ah,2;功能
mov al,1;扇区数
mov-ch,1;圆柱
mov-cl,2;部门
mov-dh,0;头
movdl,0;开车
mov bx,0x1000;
mov-es,bx;目的地(段)
mov-bx,0;目的地(抵销)
int 0x13;BIOS驱动器中断
jmp 0x1000:0;跳转到加载的代码
乘以510-($-$$)db 0;将程序调整到510 B
dw 0xAA55;引导加载程序签名
加载目标:;打印消息、按键、重新启动
jmp新东区
问候语:db“您好,欢迎使用有史以来最好的引导加载程序!”,0
提示:db“按任意键重新启动…”,0
Println:

lodsb;al您应该用实际的操作说明替换第一个
呼叫设置\u段
。正如Jester指出的,在更改SS寄存器时,始终更新SP寄存器

当前您正在读取气缸1的读数。它应该是0缸

linefeed的代码是10(而不是您编写的20)


PrintNwl中的两个BIOS调用都不需要BL寄存器,因为CR和LF都是不可显示的ascii。

您使用的是
ORG 0x7C00
这一事实意味着您希望CS:IP对或寄存器能够容纳0000h:7C00h。请记住,BIOS已经将1024字节长程序的前512字节放在线性地址00007C00h

设置其他段寄存器只是将CS复制到DS、ES和SS的问题。但非常重要的是,每次更改SS时,还必须更改SP以保持SS:SP寄存器对的一致性。在您的程序中,堆栈的方便位置将位于程序下方,因此我将SP寄存器设置为7C00h。您不能在子例程中摆弄SS:SP(就像您那样),因为最后的
RET
不知道返回到哪里

从软盘加载第二个扇区时,它必须来自0号气缸。在CHS表示中,气缸和气缸盖从0开始,扇区从1开始。
如果您检查CF的操作是否成功,那就太好了

无法通过
jmp 0x1000:0
跳转到加载的代码,因为现在位于那里的代码是使用
ORG 0x7C00
指令编译的程序的一部分。你需要对此进行补偿

  • 补偿
    ORG 0x7C00
    指令。从段零件中减去07C0h,将7C00h添加到偏移零件中。=><代码>jmp 0840h:7C00h
  • 补偿LoadTarget标签在程序内的偏移量512。从段部分减去0020h,向偏移部分加0200h。=><代码>jmp 0820h:7E00h
  • 下面是初始代码的样子

     org 7C00h
     bits 16
    main:
     mov ax,cs
     mov ds,ax  <-- Not necessary at this stage in this program
     mov es,ax  <-- (keep them should you display a message on error)
     cli
     mov ss,ax
     mov sp,7C00h
     sti
     mov ax,0201h
     mov cx,0002h
     mov dx,0000h
     mov bx,1000h
     mov es,bx
     mov bx,0000h
     int 13h
     jc  Error
     jmp 0820h:7E00h
    Error:
     hlt
    

    既然
    setup\u segments
    已经是第二个扇区,如果它还没有加载,您希望它如何工作?另外,设置
    ss
    而不设置
    sp
    是一种非常糟糕的做法,您无法知道堆栈将位于何处。@Jester哦,是的,我没有想到;)。另外,我应该在哪里将
    sp
    设置为?|哇,我简直不敢相信我把“\n”这个角色搞砸了!我知道是10,我不知道为什么我放了20。我也会修复其他的bug,谢谢!谢谢你的帮助,但它仍然显示一个空白屏幕。我正在Virtualbox上使用软盘。从使用角度看,这与真正的软盘有什么不同吗?对不起,我从未享受过使用Virtualbox的乐趣。没关系,我的程序现在可以运行了,它会重新启动,但不会显示任何内容。我认为这可能与
    sp
    有关。我不知道我该设定什么。我是否应该将
    ss
    复制到
    sp
    中?@您是否已使用
    ORG
    正确设置原点?第二阶段不应该是
    0
     ...
    new_main:
     push cs
     pop  ds
     push cs
     pop  es
     mov  si,Greeting
     call Println
     ...