带图形的Bootloader(NASM)

时间:2012-03-31 15:07:13

标签: assembly nasm bootloader

我已根据http://www.viralpatel.net/taj/tutorial/hello_world_bootloader.php

编写了简单的bootloader
[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:此代码:     [BITS 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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

您的代码注释表明您了解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"。该链接有一个简短的例子,展示了正确的用法。