本文介绍了NASM引导加载程序中的JMP$的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在尝试从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
从不执行。
此外,我们为什么要向AX添加288个?
推荐答案
$
是当前指令的地址,因此jmp $
循环到其自身。这通常是在发生致命错误时执行的。
这里,加载器是不完整的,所以它输出一条消息,然后循环。"循环"指令[希望]将被实际代码[添加]所取代。
使用db
或dw
伪操作定义的内容是数据的定义,而不是可执行指令[通常--除非您需要汇编程序不知道的特殊指令]。
因此,如果没有无限循环,您将尝试在text_string:
处执行数据,这将产生未定义/意外的结果,更不用说尝试执行引导块的最后部分了。
288
偏移量...
0x07C00
。它正在尝试在(0x07C00 + 4096 + 512)
-->0x8E00
位置设置其堆栈段。但是,它试图将其放入段寄存器,因此该值必须右移4位。0x07C0
已移位,288
是(4096 + 512) >> 4
或0x0120
。SS
的最终值是0x07C0 + 0x0120
-->[在地址0x8E00
]这似乎是错误的(即算术不匹配),但sp
寄存器设置为4096
,因此ss:sp
的最终休眠位置是地址0x9E00
。
address = (segreg << 4) + offset
。这是由硬件以某种方式访问内存的每条指令完成的。当您在代码中跳来跳去时,您使用CS
[代码段]寄存器。数据访问使用DS
[数据段]寄存器。和堆栈访问(例如push/pop
或%sp
相对),使用SS
[堆栈段]寄存器。还有一个ES
[Extra Segment]寄存器用于字符串指令。 这篇关于NASM引导加载程序中的JMP$的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!