assembly - 当您写入标签时,Assembly 是否会创建内存位置?

标签 assembly x86 x86-16 bootloader

例如,我有以下代码 ( 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... 部分并跳转到标签。

由于我是 assembly 新手,所以我有几个问题:

  • 汇编是否在您编写指令时分配内存?例如,在最后几行中,代码如下:

      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)
    

    缓冲区:分配内存?

  • 在此代码块中:

    cli             ; Disable interrupts while changing stack
    mov ss, ax
    mov sp, 4096
    sti             ; Restore interrupts
    

    为什么我们要清除“清除中断”?如果我没记错的话,这段代码分配了 4096 字节的堆栈。

    最后,在上面的 block 之后,我们有这个:

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

    我们为什么要这样做?在我看来,这样做是为了告诉Data Segment开始它的起源在哪里?

最佳答案

times 510-($-$$) db 0

这是一条(NASM)汇编器特定指令,它将在二进制(内存)中的当前偏移量处用零填充最多 510 字节的剩余可用空间。 标签本身不会创建任何 .唯一创建/分配字节的指令是 DBDWDDDQ 等。它是 <不是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

You will notice, that MyFirstLabel is only the offset where data is stored, in this case offset 0. MySecondLabel is just another offset, but it starts behind previous allocated data, in this case offset 4. My label Start for example represents offset 8 in file. So the "address" of this label is 0008h (relative to data/code segment) for example.

So in your case, if you fill the remaining memory up to 510 bytes with zeroes (this is was your times 510-($-$$) db 0 instruction is doing), allocating one additional data word (DW 0AA55h) then the offset of your buffer label is exactly 512 (0200h) (which is usually the size of the master boot record).

The cli instruction will tell the processor not to allow being interrupted until stiis called. This is important since the stack pointer register (sp) and stack segment register (ss) gets changed and this both instructions may not guaranteed to be uninterruptable. It means during changing one of these registers an interrupt may occur. In this situation the stack may be undefined/invalid. As hinted in comments to this posting, cli/sti for changing the stack segment and stack pointer isn't actually needed. See Intel documentation about "MOV" instruction:

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.

So following will be correct without cli/sti

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

以下内容不正确

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

你是对的,mov ds, ax会改变数据段寄存器。该寄存器的含义取决于我们是否运行在实模式、保护模式等下。您应该在您最喜欢的搜索引擎中搜索“x86分段内存模型”。

关于assembly - 当您写入标签时,Assembly 是否会创建内存位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32244088/

相关文章:

c - double 型矩阵 [n]x[n] 传输至 ASSEMBLY

c - SSE SIMD 代码中的性能问题

assembly - 为什么 x86 跳转/调用指令使用相对位移而不是绝对目的地?

assembly - DOSBox:debug.exe 读取文件 - 错误地处理命令

assembly - 从内存中添加一个字节到 AX 寄存器

assembly - 32位汇编语言创建输出文件麻烦

c - 传递参数 C -> NASM -> C

assembly - 如果我们有提供复杂工具的高级语言,为什么仍然需要汇编语言?

c - 哪些 C 标准库函数在底层使用 malloc

visual-studio - 在 64 位计算机上使用 Visual Studio 2010 时无法编辑并继续,应用程序面向 x86