例如,我有以下代码(MikeOS)。
jmp short bootloader_start ; Jump past disk description section
nop ; Pad out before disk description
...
...
OEMLabel db "MIKEBOOT" ; Disk label
BytesPerSector dw 512 ; Bytes per sector
SectorsPerCluster db 1 ; Sectors per cluster
ReservedForBoot dw 1 ; Reserved sectors for boot record
NumberOfFats db 2 ; Number of copies of the FAT
bootloader_start:
mov ax, 07C0h ; Set up 4K of stack space above buffer
add ax, 544 ; 8k buffer = 512 paragraphs + 32 paragraphs (loader)
...
...
....
现在,我知道jmp short bootloader_start
意味着它跳过OEMLabel...
部分并跳转到标签。
由于我不熟悉集会,我有几个问题:
汇编在写入指令时是否分配内存?例如,在最后几行中,代码如下:
times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros
dw 0AA55h ; Boot signature (DO NOT CHANGE!)
buffer: ; Disk buffer begins (8k after this, stack starts)
buffer:
分配内存?
在此代码块中:
cli ; Disable interrupts while changing stack
mov ss, ax
mov sp, 4096
sti ; Restore interrupts
为什么我们要清除中断?如果我没错,这段代码会分配4096字节的堆栈。
最后,在上述块之后,我们有了这个:
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
为什么我们这样做?在我看来,这样做是为了告诉数据段从哪里开始?
答案 0 :(得分:6)
times 510-($-$$) db 0
这是一个(NASM)汇编程序特定的指令,它将填充剩余的可用空间,最多510个字节,并在二进制(内存)中的当前偏移处使用零。
它自己的标签将不创建任何标签。创建/分配字节的唯一指令是DB
,DW
,DD
,DQ
等。它是否 cpu指令,但是由汇编程序解释的宏。
编辑(标签是什么?):
标签只表示偏移量(内存中或二进制文件中的地址)。以下面为例:
MyFirstLabel:
db 1, 2, 3, 4
MySecondLabel:
db 5, 6, 7, 8
Start:
如果这是你的汇编程序文件并且在偏移0处加载到内存中,它将如下所示:
OFS DATA 0000h: 01 02 03 04 0004h: 05 06 07 08
您会注意到,MyFirstLabel
只是存储数据的偏移量,在这种情况下偏移量为0. MySecondLabel
只是另一个偏移量,但它从先前分配的数据开始,在这种情况下偏移量4.我的标签Start
例如表示文件中的偏移量8。因此,该标签的“地址”是0008h(相对于数据/代码段),例如。
所以在你的情况下,如果你用零填充剩余的内存最多510个字节(这是你的times 510-($-$$) db 0
指令正在做的事情),分配一个额外的数据字(DW 0AA55h
)然后偏移您的buffer
标签正好是512(0200h)(通常是主引导记录的大小)。
cli
指令将告诉处理器在调用sti
之前不允许中断。这很重要,因为堆栈指针寄存器(sp)和堆栈段寄存器(ss)会发生变化,这两条指令可能不会保证不会中断。这意味着在更改其中一个寄存器期间可能会发生中断。在这种情况下,堆栈可能是未定义/无效的。正如在这篇文章的评论中暗示的那样,实际上并不需要改变堆栈段和堆栈指针的cli / sti。请参阅有关“MOV”指令的英特尔文档:
使用MOV指令加载SS寄存器会禁止所有中断,直到执行下一条指令为止。此操作允许使用下一条指令将堆栈指针加载到ESP寄存器中(MOV ESP, 在发生中断之前的堆栈指针值。
如果没有cli / sti
,那么以下是正确的mov bx, 4096
mov ss, ax
mov sp, bx
以下是不正确的
mov ss, ax
mov ax, 4096
mov sp, ax
您是对的,mov ds, ax
将更改数据段寄存器。该寄存器的含义取决于我们是以实模式,保护模式等运行。您应该在您最喜欢的搜索引擎中搜索“x86分段存储模型”。