【发布时间】:2011-10-02 11:01:41
【问题描述】:
**请注意,当我说启动程序时,我并不是指启动操作系统的程序。我的意思是,当您启动计算机并执行某些操作时运行的简单程序。
好吧,所以我非常精通 Assembly/NASM,但我认为我对它的掌握程度足以编写简单的引导程序。
嗯,我认为我已经掌握了足够好的知识。显然不是。
我尝试了一个在网上找到的简单启动程序。它运行良好(打印字母“A”)。然后我修改它以打印存储在内存中的字母。它失败了;它不是打印一个“A”,而是打印一个笑脸。 (我发誓,电脑现在在嘲笑我。)
这是源文件中的代码:
[BITS 16] ; We start up in 16-bit real mode
[ORG 0x7C00] ; We're booted into memory at this address. (Or so I'm told)
mov ah, 0x0E ; Teletype command
mov bh, 0x00 ; Page number
mov bl, 0x07 ; Attributes (7 == white foreground, black background)
mov al, [testChar] ; Character to print; load it from the memory referenced by testChar.
int 0x10 ; Tell the BIOS to execute the teletype command.
jmp $ ; Infinite loop prevents us from going off and executing the other junk in memory
testChar db 65 ; This is the character we want to print. 'A'.
; The following code pads the rest of the outputted binary file
; and concludes it with the bootloader signature so I don't have
; to do so manually.
times 510-($-$$) db 0
dw 0xAA55
如果我将 'move al, [testChar]' 替换为 'move al, 65',则字母 'A' 打印正确。我尝试过移动内存声明,尝试了所有括号组合或 BITS 和 ORG 周围没有括号,并且尝试增加和减少 testChar(即 [testChar+1])。每次,它都会打印一个笑脸、一个反向笑脸(当我增加 testChar 时),或者什么都不打印(当我将内存声明放在代码之前,可能是因为没有执行代码 =P)。我不能让这该死的东西工作。
现在,对于规范(因为它们可能是相关的):
我正在运行带有 Intel Pentium II 处理器的 Dell Latitude CPi,因为这就是我要测试的全部内容(我不是用我的普通计算机测试汇编程序。见鬼。)。我很确定说处理器是 x86,因为我在上面运行过 Windows XP、Ubuntu 和 Arch Linux。
我目前正在使用 NASM 在 Arch Linux 上编写和编译程序。
引导程序从软盘运行
我使用 'nasm -f bin FILENAME' 来编译代码。
然后我使用 AL 的“mtools”包中的“mformat”命令通过“mformat -f 1440 -B BOOTPROGRAM A:'。
那么,这次我搞砸了什么?还是我的处理器/BIOS 有问题?
【问题讨论】:
-
笑脸可能意味着它正在打印 ascii 字符 1,这意味着您没有正确使用
[testChar]。我的 ASM 太生疏了,不记得如何正确操作了…… -
我想可能就是这样。问题是,我看不到任何其他方法可以做到这一点。 NASM 手册说如果我想从一个地址(实际上是 testChar)中获取内存,我必须把它放在括号中。当我查看实际的二进制文件时,相对于程序的开始,testChar 应该是 0x0e 之类的东西。因此,如果我输入
testChar,它会将 0x0e 放入 AL 寄存器。但是如果我输入[testChar],它应该将存储的值放在地址0x0e。但是,相反,它似乎更喜欢放置一个 1(或任何笑脸的 ASCII 键)而不是进入内存。 -
“引导程序”的术语是引导加载程序。
标签: assembly memory-management nasm bootloader