首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BIOS改为部门

BIOS改为部门
EN

Stack Overflow用户
提问于 2015-07-10 15:27:20
回答 2查看 1K关注 0票数 2

为了学习,我研究了制作一个小型操作系统,现在我正在使用引导加载程序。我希望能够使用int 0x13从软盘驱动器读取扇区,将它们放入内存,然后跳转到该代码中。以下是我到目前为止所拥有的:

代码语言:javascript
复制
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

我想在LoadTarget之后将扇区加载到address 0x1000:0中,然后跳转到它。到目前为止我只得到了一个空白的屏幕。我觉得这个bug介于main和行times 510 - ($-$$) db 0之间。也许我只是没有得到寄存器的值对吧?请帮帮我!谢谢

EN

回答 2

Stack Overflow用户

发布于 2015-07-10 16:32:05

您应该将第一个call setup_segments替换为执行任务的实际指令。此外,正如Jester指出的,在更改SS寄存器时,始终更新SP寄存器。

目前,您正在从第一缸阅读。应该是圆柱0。

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

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

票数 5
EN

Stack Overflow用户

发布于 2015-07-12 15:54:15

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

设置其他段寄存器只是将CS复制到DS、ES和SS的问题。但是非常重要的是,每次你改变党卫军,你也必须改变SP,以保持一个连贯的SS:SP对寄存器。在您的程序中,堆栈的一个方便位置应该在程序下面,所以我用7C00h设置了SP寄存器。您不能在子程序中摆弄SS:SP (就像您所做的那样),因为最后的RET将不知道返回到哪里!

当你从软盘加载第二扇区时,它必须来自气缸0。在CHS中,代表缸和头从0开始,扇区从1开始。

如果您检查CF以获得成功的操作,那就太好了。

跳到加载的代码不能通过jmp 0x1000:0完成,因为现在位于那里的代码是使用ORG 0x7C00指令编译的程序的一部分。你需要补偿这一切!

  1. 补偿ORG 0x7C00指令。从段部分减去07C0h,将7C00h添加到偏移部分。=> jmp 0840h:7C00h
  2. 补偿您的LoadTarget标签在程序中的偏移量512。从段部分减去0020小时,将0200 h加到偏移部分。=> jmp 0820h:7E00h

下面是初始代码的样子

代码语言:javascript
复制
 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

一旦第二阶段运行,您只需要设置DS和ES寄存器。CS:IP是通过JMP设置的,SS:SP只是继续。

代码语言:javascript
复制
 ...
new_main:
 push cs
 pop  ds
 push cs
 pop  es
 mov  si,Greeting
 call Println
 ...
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31344628

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档