我正在以实模式学习编程,并在SO上发现了一篇对我来说非常有用的帖子 但我对在给定代码中如何工作有一些疑问
;This is NASM
BITS 16 ; 16 bits!
start: ; Entry point
mov ax, 07C0h ; Move the starting address (after this bootloader) into 'ax'
add ax, 288 ; Leave 288 bytes before the stack beginning for some reason
mov ss, ax ; Show 'stack segment' where our stack starts
mov sp, 4096 ; Tell 'stack pointer' that our stack is 4K in size
mov ax, 07C0h ; Use 'ax' as temporary variable for setting 'ds'
mov ds, ax ; Set data segment to where we're loaded
mov si, text_string ; Put string position into SI (the reg used for this!)
call print_string ; Call our string-printing routine
jmp $ ; Jump here - infinite loop!
text_string db 'This is my cool new OS!', 0 ; Our null terminated string
; For some reason declared after use
print_string: ; Routine: output string in SI to screen
mov ah, 0Eh ; I don't know what this does..
; Continue on to 'repeat'
.repeat:
lodsb ; Get character from DS:SI into AL
cmp al, 0 ; If end of text_string
je .done ; We're done here
int 10h ; Otherwise, print the character (What 10h means)
jmp .repeat ; And repeat
.done:
ret
times 510-($-$$) db 0 ; Pad remainder of boot sector with 0s
dw 0xAA55 ; The standard PC 'magic word' boot signature
1)DS和CS是否重叠?
2)CS是否从0h位置开始?,附加的图像显示由汇编程序生成的512个字节的引导扇区
3)DS和CS都是从07c00H开始的吗?首先,代码部分已填充 在放入文本字符串的数据之前
4)堆栈是从07c00 + 288开始的?和mov sp,4096将定义大小的堆栈(07c00 + 288 + 4096-07c00 + 288)。
答案 0 :(得分:1)
简短回答:是的。实模式段:偏移地址可以并且确实重叠。您的BIOS在7C00h加载bootsector。这可能是cs
零,偏移7C00h(尽管有传闻称某个Compac Presario BIOS在07C0:0000加载)。这是同一个地址!我们乘以16,因为这是在实模式下计算地址的方式 - 段乘以16加偏移量。我们可以将数字4位向左移动乘以16 - 一个十六进制数字,如果你这样看的话。
引导程序通常在顶部说org 7C00h
。由于此代码没有org
,因此Nasm假设org 0
。在这个“常见”引导程序中,我们将{0}放入ds
(和es
?)。使用org 0
,我们需要ds
中的7C0h。 0000:7C00h和07C0h:0000是相同的地址。找到text_string
非常重要。
你发现的代码中的注释有点欺骗性......它实际上不是“288字节”。将其写成十六进制可能更容易 - 120h。将其加到7C0h得到8E0h。然后sp
加载4096十进制或1000h。因此,堆栈的线性地址(段* 16 +偏移)从9E00h开始向下工作到8E00h - 有足够的空间避免在7C00h到7E00h时碰到你的代码(512位小数= 200h是bootsector的大小)。 / p>
可能值得注意的是,您的“数据”位于代码中间,但它处于无法执行的位置,所以没关系。
我希望我的算术运算正确,并且没有让你更加困惑!
答案 1 :(得分:0)
mov ax, 07C0h ; Move the starting address (after this bootloader) into 'ax'
add ax, 288 ; Leave 288 bytes before the stack beginning for some reason
mov ss, ax ; Show 'stack segment' where our stack starts
这会设置您的堆栈段。段寄存器是地址中的第4位到第19位。因此,您的堆叠细分受众群从地址07C00h + 288*16
或08180h
开始(您向ax
添加了288位小数,其中包含07C0h
,然后您移动了到段寄存器)。
mov sp, 4096 ; Tell 'stack pointer' that our stack is 4K in size
只有当您知道地址范围08180h
到0917Fh
可用于堆栈时,才会为您提供4k堆栈。
mov ax, 07C0h ; Use 'ax' as temporary variable for setting 'ds'
mov ds, ax ; Set data segment to where we're loaded
这会将数据段设置为从地址07C00h
开始。
我不知道您的列表中的代码段开始位置或cs
设置的位置,因此不清楚cs
和ds
是否重叠。 cs
通常不会从0
开始。