Assembly 会在您写标签时创建内存位置吗?

Does Assembly create memory locations the moment you write a label?

比如我有下面的代码(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

这是一条 (NASM) 汇编器特定指令,它将在二进制文件(内存)的当前偏移量处用零填充剩余的 space 最多 510 个字节。 它自己的标签 不会 创建任何 .唯一会 create/allocate 字节的指令是 DBDWDDDQ 等。它是 no 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。所以这个标签的"address"例如是0008h(相对于data/code段)。

所以在你的情况下,如果你用零填充剩余内存最多 510 个字节(这是你的 times 510-($-$$) db 0 指令正在做的),分配一个额外的数据字 (DW 0AA55h) 然后buffer 标签的偏移量正好是 512 (0200h)(通常是主引导记录的大小)。

cli 指令将告诉处理器在调用 sti 之前不允许被中断。这一点很重要,因为堆栈指针寄存器 (sp) 和堆栈段寄存器 (ss) 会发生变化,并且这两条指令 可能不会 保证是不间断的。这意味着在更改这些寄存器之一期间可能会发生中断。在这种情况下,堆栈可能是 undefined/invalid。正如对此帖子的评论中所暗示的,实际上并不需要用于更改堆栈段和堆栈指针的 cli/sti。请参阅有关 "MOV" 指令的英特尔文档:

Loading the SS register with a MOV instruction inhibits all interrupts until after the execution of the next instruction. This operation allows a stack pointer to be loaded into the ESP register with the next instruction (MOV ESP, stack-pointer value) before an interrupt occurs.

所以如果没有 cli/sti

,下面的内容也是正确的
mov bx, 4096
mov ss, ax 
mov sp, bx

以下不正确

mov ss, ax 
mov ax, 4096
mov sp, ax

你说得对,mov ds, ax会改变数据段寄存器。这个寄存器的含义取决于我们是运行在实模式还是保护模式等。你应该在你喜欢的搜索引擎中搜索"x86 segmented memory model"。

记忆一直都在。 buffer:只是给它起一个象征性的名字。

禁用中断以防止其他进程干扰可能需要多个指令的东西。专门用于设置堆栈,您不必这样做,因为设置 ss 寄存器将禁用下一条指令的中断。目的是您也应该有时间设置 sp

无论如何,在完成后启用中断可能是个好主意,因为它们最初可能没有启用。

ds 寄存器必须设置为您要执行的代码假定的段。否则程序将找不到您的变量。