NASM bootloader中的jmp $

时间:2016-03-03 04:04:03

标签: assembly nasm bootloader bios x86-16

我试图从Bootloader编写引导加载程序。编写的代码是

BITS 16

start:
    mov ax, 07C0h       ; Set up 4K stack space after this bootloader
    add ax, 288     ; (4096 + 512) / 16 bytes per paragraph
    mov ss, ax
    mov sp, 4096

    mov ax, 07C0h       ; Set data segment to where we're loaded
    mov ds, ax


    mov si, text_string ; Put string position into SI
    call print_string   ; Call our string-printing routine

    jmp $           ; Jump here - infinite loop!


    text_string db 'This is my cool new OS!', 0


print_string:           ; Routine: output string in SI to screen
    mov ah, 0Eh     ; int 10h 'print char' function

.repeat:
    lodsb           ; Get character from string
    cmp al, 0
    je .done        ; If char is zero, end of string
    int 10h         ; Otherwise, print it
    jmp .repeat

.done:
    ret


    times 510-($-$$) db 0   ; Pad remainder of boot sector with 0s
    dw 0xAA55       ; The standard PC boot signature

我无法理解的是为什么我们写jmp $。通过编写jmp $,它进入无限循环。因此,在进入无限循环后,最后两行

times 510-($-$$) db 0   ; Pad remainder of boot sector with 0s
    dw 0xAA55       ; The standard PC boot signature

永远不会被执行。

此外,我们为什么要向斧头添加288?

2 个答案:

答案 0 :(得分:3)

$是当前指令的地址,因此jmp $循环到自身。这通常是为了致命的错误。

这里,加载器不完整,因此它输出一条消息然后循环。 "循环"指令[希望]将被实际代码[将被添加]取代。

使用dbdw伪操作定义的内容是数据的定义,并且不是可执行指令[通常 - 除非您需要汇编程序不知道的特殊指令。

因此,如果没有无限循环,您将尝试在text_string:执行数据,这会产生未定义/意外结果,更不用说尝试执行引导块的最后部分了。

288偏移......

引导加载到地址0x07C00。它正试图在位置(0x07C00 + 4096 + 512) - >设置其堆栈段。 0x8E00。但是,它试图将其放入段寄存器中,因此该值必须右移4位。 0x07C0 已经转移,288(4096 + 512) >> 40x0120SS的最终值为0x07C0 + 0x0120 - > 0x08E0 [地址0x8E00]

这似乎是错误的(即算术不匹配),但sp寄存器设置为4096,因此ss:sp的最终静止位置是地址{{ 1}}。

在8086实模式寻址中,所有地址都使用段寄存器和一些偏移量。最终地址是:0x9E00。这可以通过以某种方式访问​​内存的每条指令上的硬件来完成。

当您在代码中跳转时,使用address = (segreg << 4) + offset [代码段]寄存器。数据访问使用CS [数据段]寄存器。并且堆栈访问(例如DSpush/pop相对,使用%sp [堆栈段]寄存器。还有一个SS [extra segment]寄存器用于字符串指令。

答案 1 :(得分:0)

最后两个语句不是可执行语句,它们是一种伪指令或汇编程序指令。这里,它们用于组装目标代码而不是一些可执行指令,并确保引导扇区为512字节。

jmp $是一个可执行指令,将在加载程序加载后运行。汇编程序在将汇编代码汇编到目标文件中时使用(而不是执行)最后两行。