简单的NASM“启动程序”无法正确访问内存?

时间:2011-07-11 01:13:51

标签: assembly memory-management nasm bootloader

**请注意,当我说启动程序时,我并不是指启动操作系统的程序。我的意思是,当你启动计算机并执行某些操作时运行的简单程序。

好吧,所以我不是非常精通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

如果我用“移动al,65 ”替换“移动al,[testChar] ”,则会正确打印字母“A”。我试过移动内存声明,我尝试了BITS和ORG周围的括号或括号的每个组合,我尝试递增和递减testChar(即[testChar + 1])。每次打印时都会显示一个笑脸,一个反向笑脸(当我增加testChar时),或者什么都没有(当我在代码之前放入内存声明时,可能是因为没有执行代码= P)。我无法得到该死的东西。

现在,对于规范(因为它们可能相关):

  • 我正在使用英特尔奔腾II处理器运行戴尔Latitude CPi,因为这是我必须测试的所有内容(我没有使用普通计算机测试汇编程序。没有。)。我很确定说处理器是x86,因为我在它上面运行Windows XP,Ubuntu和Arch Linux。

  • 我目前正在使用NASM在Arch Linux上编写和编译程序。

  • 启动程序从软盘运行

  • 我使用' nasm -f bin FILENAME '来编译代码。

  • 然后我使用'mtools'软件包中的'mformat'命令将AL通过' mformat -f 1440 -B BOOTPROGRAM A:将编译后的引导程序传输到软盘上/ EM> ”。

那么,这次搞砸了什么?或者我的处理器/ BIOS有问题吗?

3 个答案:

答案 0 :(得分:3)

DS可能充满了一些垃圾值,所以只需:

push cs
pop ds

mov ax, cs
mov ds, ax
mov es, ax

更好的是,不要相信CS并且做:

xor ax, ax
mov ds, ax

请参阅this discussion:某些BIOS可能使用07c0:0000而不是传统的0000:7c00,特别是在使用ElTorito从CD-ROM启动时。

答案 1 :(得分:0)

这产生了以下代码(只需在编译的代码上运行objdump)。

00000000  B40E              mov ah,0xe
00000002  B700              mov bh,0x0
00000004  B307              mov bl,0x7
00000006  A00D7C            mov al,[0x7c0d]
00000009  CD10              int 0x10
0000000B  EBFE              jmp short 0xb
0000000D  41                inc cx ; this is actually your testChar
                                   ; ignore the opcode translation

现在,如果你位于0x7C00,那么[0x7c0d]将是其中的最后一个字节(即0x41或65,或ASCII“A”)。但是,如果像其他贡献者之一(ninjalj)提到你有一些奇怪的BIOS错误,这意味着你不在0x7C00,那么[0x7c0d]是任何人的猜测。

答案 2 :(得分:0)

我第一次跑的时候运行得很好!它打印'A'。使用命令nasm [filename.asm] -o [filename.com] -l [filename.lst]

我使用了nasm OSbad.asm -o OSbad.com。使用MagicISO制作可启动映像文件OSbad.iso并使用Windows磁盘刻录机将其刻录到DVD / RW。加载了Oracle VM并制造了一个新的虚拟机,具有256 Mb RAM,CD / DVD,2GB硬盘。用DVD启动,然后在屏幕上打印“A”。

所以我猜你的程序正在运行。必须是你正在做的其他事情使它无法正常工作。