Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/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 NASM引导加载程序中的jmp$_Assembly_Nasm_Bootloader_Bios_X86 16 - Fatal编程技术网

Assembly NASM引导加载程序中的jmp$

Assembly NASM引导加载程序中的jmp$,assembly,nasm,bootloader,bios,x86-16,Assembly,Nasm,Bootloader,Bios,X86 16,我正试图从中编写引导加载程序。编写的代码是 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 whe

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

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添加到ax?

$是当前指令的地址,因此jmp$正在循环到自身。通常针对致命错误执行此操作

在这里,加载程序是不完整的,所以它输出一条消息,然后循环。循环指令[希望]将被[待添加的]实际代码所取代

用db或dw伪操作定义的东西是数据的定义,不是可执行指令[通常除非您需要汇编程序不知道的特殊指令]

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

288偏移量

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

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


在8086实模式寻址中,所有地址都使用一个段寄存器和一些偏移量。最后的地址是:address=segreg最后两条语句不是可执行语句,它们是伪指令或汇编指令。在这里,它们用于组装目标代码而不是一些可执行指令,并确保引导扇区为512字节


然而,jmp$是一条可执行指令,将在加载程序加载它之后运行。当汇编程序将汇编代码汇编成一个目标文件时,最后两行是使用的,而不是由汇编程序执行的。

那么,它在打印后没有任何事情要做,因此,无限循环是避免执行文本字符串及其后的任何内容的最佳方法。将288添加到0x7c0并将其存储在堆栈段中只会在堆栈和引导加载程序之间留出空间。中间的内存区域可以用作磁盘缓冲区等。您可能还会遇到jmp$的另一个变体是序列cli endloop:hlt jmp endloop。结果是定义的,可能是意外的。这意味着最后两行永远不会执行?@RichaTibrewal Right。你也不希望它们成为指令,因为它们不是指令。做dw就像做无符号短xx=0xAA55;在C语言中,你不会试图在C语言中执行这些,是吗?你能解释一下代码的前六行吗?@MichaelPetch每次我(后来)编辑时,我都意识到数学是错误的。我先是手工操作,然后是kcalc,最后是perl。我几乎要添加一个免责声明:十六进制数学不准确,我很累:-