Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 引导加载程序没有';不要跳转到内核代码_Assembly_Virtualbox_Nasm_X86 16_Bootloader - Fatal编程技术网

Assembly 引导加载程序没有';不要跳转到内核代码

Assembly 引导加载程序没有';不要跳转到内核代码,assembly,virtualbox,nasm,x86-16,bootloader,Assembly,Virtualbox,Nasm,X86 16,Bootloader,我正在写一个小的操作系统-用于实践。我从引导加载程序开始。我想创建以16位实模式运行的小型命令系统(目前)。 我创建了一个引导加载程序,它重置驱动器,然后在引导加载程序之后加载扇区。 问题是因为在jmp函数之后,实际上什么都没有发生 我并没有尝试在0x7E00加载下一个扇区(我不完全确定如何使用es:bx指向地址,所以这可能是个问题,我相信它的地址是偏移量),只是在引导加载程序之后 代码如下: ; ; SECTOR 0x0 ; ;dl is number of harddrive where

我正在写一个小的操作系统-用于实践。我从引导加载程序开始。
我想创建以16位实模式运行的小型命令系统(目前)。
我创建了一个引导加载程序,它重置驱动器,然后在引导加载程序之后加载扇区。
问题是因为在
jmp
函数之后,实际上什么都没有发生

我并没有尝试在0x7E00加载下一个扇区(我不完全确定如何使用es:bx指向地址,所以这可能是个问题,我相信它的地址是偏移量),只是在引导加载程序之后

代码如下:

;
; SECTOR 0x0
;

;dl is number of harddrive where is bootloader
org 0x7C00
bits 16

;reset hard drive
xor ah,ah
int 0x13
;read sectors
clc
mov bx,0x7E00
mov es,bx
xor bx,bx
mov ah,0x02 ;function
mov al,0x1  ;sectors to read
mov ch,0x0  ;tracks
mov cl,0x1  ;sector
mov dh,0x0  ;head
int 0x13
;if not readed jmp to error
jc error
;jump to 0x7E00 - executed only if loaded
jmp 0x7E00
error:
    mov si,MSGError
    .loop:
        lodsb
        or al,al
        jz .end
        mov ah,0x0E
        int 0x10
        jmp .loop
    .end:
        hlt
MSGError db "Error while booting", 0x0
times 0x1FE - ($ - $$) db 0x0
db 0x55
db 0xAA

;
; SECTOR 0x1
;

jmp printtest
;definitions
MSGLoaded db "Execution successful", 0x0
;
; Print function
; si - message to pring (NEED TO BE FINISHED WITH 0x0)

printtest:
    mov si,MSGLoaded
    .loop:
        lodsb
        or al,al
        jz .end
        mov ah,0x0E
        int 0x10
        jmp .loop
    .end:
        hlt

times 0x400 - ($-$$) db 0x0

我一直在使用VirtualBox测试这段代码,但实际上什么都没有发生,读取错误没有显示,以及应该打印的消息。

这段代码的主要问题是:

  • ES:BX指向错误的段:偏移量以将内核加载到
  • 加载了错误的扇区,所以内核不是预期的
  • 第一个是在这个代码中:

    mov bx,0x7E00
    mov es,bx
    xor bx,bx
    

    问题是要将扇区从磁盘加载到
    0x0000:0x7E00
    (ES:BX)。此代码将ES:BX设置为
    0x7E00:0x0000
    ,解析为
    0x7E000
    (在发出任何BIOS中断之前,您需要设置堆栈(
    SS
    SP
    寄存器)。在使用lodsb和相关函数之前,您还需要调用
    CLD
    STD
    。在设置堆栈调用
    CLD
    之后,您的代码假定为自动递增。您似乎也没有使用适当的段设置
    DS
    寄存器(否则lodsb可能无法工作)。从您所展示的内容来看,还不清楚内核映像的原点设置为什么。您用来链接、编译和创建磁盘映像的makefile或命令可能对您的问题有帮助。
    mov-bx,0x7E00
    mov-es,bx
    xor-bx,bx
    似乎有误。您的代码表明您打算拒绝d磁盘上的扇区位于
    0x0000:0x7E00
    =物理地址
    0x7E00
    ,但您将
    ES
    BX
    段设置为
    0x7E00
    并将
    BX
    设置为零,从而产生0x7E00的物理地址。我的内核起始点是扇区0x1。我正在使用
    nasm bootloader.asm-o bootloader.img>编译(bootloader.asm是主线程中的代码)。然后在VirtualBox中将bootloader.img设置为软盘。关于
    lodsb`它在
    jc
    时起作用,我使用
    jnc
    在读取实际成功完成时显示错误消息。您说什么也不打印,我认为这主要是因为您没有设置
    lodsb
    所需的
    DS
    寄存器。a启动引导加载程序时,您应该手动设置
    DS
    ,在这种情况下,它应该设置为0。因此
    xor ax,ax
    mov DS,ax
    (或任何等效于将0移动到DS的操作)肯定会有所帮助。我相信,您看到的任何打印内容都可能是因为DS错误(未设置)。你不能依靠BIOS跳转到你的引导加载程序,并为DS、ES、SS和SPS设置正确的值。你的扇区号是对的,我已经更改了,内核正常打印了消息。我不知道为什么会打印“Ä”┼╝" 以前是,但现在可以了。我真的很感激。当一个人在x86上使用GNU汇编程序时,它看起来像是
    。英特尔语法noprefix
    jmp 0x07E0:0x0000
    ,您在这里写了“解析此代码的第一项和第二项”",代码段初始化了寄存器DS、ES、SS和SP。那么CS寄存器呢,我们应该保持这个寄存器不变吗?或者您建议做什么更改?@supmethods:这是一个好问题。关于这个主题,我在这里有一个问题和答案:。如果引导加载程序使用指令at是相对于CS的。很多引导加载程序代码并不要求CS是一个特定的值。Q&A链接显示了一些可能出现这种情况的场景。如果您编写引导加载程序来避免它们,那么就可以了。如果您不确定,您可以在引导加载程序的开始处进行JMP来设置CS。抱歉,我没有阅读注释和surro当我发表评论的时候,我会发短信。是的,这是一个坏习惯。
    mov ah,0x02 ;function
    mov al,0x1  ;sectors to read
    mov ch,0x0  ;tracks
    mov cl,0x2  ;sector number
    mov dh,0x0  ;head
    int 0x13
    
    mov cl,0x2  ;sector number
    
    xor ax,ax      ; We want a segment of 0 for DS for this question
    mov ds,ax      ;     Set AX to appropriate segment value for your situation
    mov es,ax      ; In this case we'll default to ES=DS
    mov bx,0x8000  ; Stack segment can be any usable memory
    
    cli            ; Disable interrupts to circumvent bug on early 8088 CPUs
    mov ss,bx      ; This places it with the top of the stack @ 0x80000.
    mov sp,ax      ; Set SP=0 so the bottom of stack will be @ 0x8FFFF
    sti            ; Re-enable interrupts
    
    cld            ; Set the direction flag to be positive direction
    
    jmp 0x07E0:0x0000
    
    db 0x0ea     ; Far Jump instruction
    dw 0x0000    ; Offset
    dw 0x07E0    ; Segment
    
    ljmpw $0x07E0,$0x0000