【问题标题】:Bootloader with graphics (NASM)带图形的引导加载程序 (NASM)
【发布时间】:2023-12-24 17:23:01
【问题描述】:

我编写了简单的引导加载程序,基于:http://www.viralpatel.net/taj/tutorial/hello_world_bootloader.php

[BITS 16]   ;16bit
[ORG 0x7C00]    ;offset

MOV AH, 0x00 ; change video mode
MOV AL, 0x13 ; 0x13
INT 0x10 ; interrupt
CALL DrawTenLines   ;lets draw
JMP $       ;hang it

DrawOneLine:
MOV CX, 0x00 ;x = 0

nextpixel:
MOV AH, 0x09 ;func number - WritePixelOnScreen [wiki]
MOV AL, 0x05 ;color - Magenta
MOV BH, 0x00 ;Page no
INT 0x10 ;Video interrupt - BIOS
CMP CX, 10 ;if (x == 10) {
JE exitfunc ;exit function } else {
JNE nextpixel ;next pixel }
ADD CX, 0x01 ;add one :D
exitfunc: ;exit :D
RET

DrawTenLines: ;draw some lines
MOV DX, 0x00 ;y = 0
CALL DrawOneLine
MOV DX, 0x01 ;y = 1
CALL DrawOneLine
MOV DX, 0x02 ;y = 2
CALL DrawOneLine
MOV DX, 0x03 ;y = 3
CALL DrawOneLine
MOV DX, 0x04 ;y = 4
CALL DrawOneLine
MOV DX, 0x05 ;y = 5
CALL DrawOneLine
RET

;Data

TIMES 510 - ($ - $$) db 0   ;Fillers
DW 0xAA55           ;boot signature

但这并没有按预期工作 - 不绘制,只有黑屏和挂起(如预期)。

使用 NASM 编译,-f bin。该站点的示例有效。在 Virtualbox 中测试。

编辑:忘记更改视频模式 - 但仍然无法正常工作。

编辑 2:此代码: [位 16] ;16 位 [ORG 0x7C00] ;偏移量

MOV AH, 0x00
MOV AL, 0x13
INT 0x10
MOV AH, 0x09 ;WritePixelOnScreen [wiki]
MOV AL, 0x0F ;color - White
MOV BH, 0x00 ;page no. 
MOV CX, 1 ;x
MOV DX, 1 ;y
INT 0x10 ;interrupt
MOV CX, 2 ;x
MOV DX, 1 ;y
INT 0x10 ;interrupt
MOV CX, 3 ;x
MOV DX, 1 ;y
INT 0x10 ;interrupt
JMP $       ;hang

;Data

TIMES 510 - ($ - $$) db 0   ;filler
DW 0xAA55           ;boot signature

制作: http://i.imgur.com/UGS3m.png

【问题讨论】:

  • 顺便说一句。第二部分是怎么回事?你也可以帮我做一个吗?

标签: assembly nasm bootloader


【解决方案1】:

简答:我认为这两行:

MOV CX, [EAX] ;x
MOV DX, [EBX] ;y

应该是:

MOV CX, AX ;x
MOV DX, BX ;y

(无方括号,使用低 16 位。)

更长的答案:我不认为代码挂在您认为的位置。由于这两行,我希望它会挂起:

MOV CX, [EAX] ;x
MOV DX, [EBX] ;y

您的代码 cmets 表明您了解 C,因此我将用这些术语进行解释。说明:

MOV EAX, 0x00
MOV CX, [EAX]

等价于:

unsigned int EAX = 0;
unsigned short CX;
CX = (unsigned short)(*EAX);

我的选角可能不正确。关键是在 EAX ("[EAX]") 周围放置方括号使用 EAX 的内容作为指针。我希望您的代码取消引用 NULL 指针,这可能会导致挂起。

编辑,根据您的更新

您正在尝试使用此中断在屏幕上写入一个像素:

MOV AH, 0x09 ;func number - WritePixelOnScreen [wiki]
MOV AL, 0x05 ;color - Magenta
MOV BH, 0x00 ;Page no
INT 0x10 ;Video interrupt - BIOS

我在那里看不到任何坐标参数。我查看了 int 10h 函数,发现 AH=09h 是"write character and attribute at cursor position"——不是你想要的。看看AH=0Ch -- "change color for a single pixel"。该链接有一个简短的示例,演示了正确的用法。

【讨论】:

  • 我用 CX 替换了 EAX,用 DX 替换了 EBX,并删除了对 EAX 和 EBX 的所有引用,但仍然无法正常工作
  • 您可能需要更新问题中的代码。我不理解您所做的更正,或者如果我理解它们,它们是不正确的。
  • 但是@up 已经发布了同样的问题。
【解决方案2】:

DrawOneLine 中有一个无限循环。此行永远不会被执行:

ADD CX, 0x01 ;add one :D

你的循环代码应该看起来更像这样:

CMP CX, 10 ;if (x == 10) {
JE exitfunc ;exit function } else {
ADD CX, 0x01 ;add one :D
JMP nextpixel ;next pixel }

我认为您的问题可能是使用了错误的视频模式。您将视频模式设置为模式 0x13,然后调用 INT 0x10, AH=0x09,我认为这是一个文本模式功能。 IIRC,0x13模式的屏幕数据位于0xA000:0x0000,可以直接写入。

编辑:我认为 INT 0x10, AH=0x0C 是您尝试使用的,而不是 INT 0x10, AH=0x09

【讨论】:

  • 谢谢,这解决了我的问题。
最近更新 更多