Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly ASM子例程,用于在屏幕上的特定位置打印彩色文本_Assembly_Nasm_Bootloader_Bios - Fatal编程技术网

Assembly ASM子例程,用于在屏幕上的特定位置打印彩色文本

Assembly ASM子例程,用于在屏幕上的特定位置打印彩色文本,assembly,nasm,bootloader,bios,Assembly,Nasm,Bootloader,Bios,我正在尝试编写一些ASM代码,这些代码将使用BIOS中断向显示器写入一些文本。此代码将从引导扇区运行 我有 msgtextdb“你好”;正文 msgCol DB 0x07,0x08,0x09,0x0A,0x0B;颜色 msgXY DW 0x0E26;列/行 msgLen DB 0x05;长度 信息只是“你好”,每个字母都有不同的颜色。消息在屏幕上的位置大致在中间,长度为5。 我想写一个函数,将任何消息/颜色/xy/长度写入屏幕,但现在,让我们关注这个函数 打印: MOV-AH,0x02;告诉B

我正在尝试编写一些ASM代码,这些代码将使用BIOS中断向显示器写入一些文本。此代码将从引导扇区运行

我有

msgtextdb“你好”;正文
msgCol DB 0x07,0x08,0x09,0x0A,0x0B;颜色
msgXY DW 0x0E26;列/行
msgLen DB 0x05;长度
信息只是“你好”,每个字母都有不同的颜色。消息在屏幕上的位置大致在中间,长度为5。

我想写一个函数,将任何消息/颜色/xy/长度写入屏幕,但现在,让我们关注这个函数

打印:
MOV-AH,0x02;告诉BIOS我们要设置光标位置
MOV-DX[msgXY];告诉BIOS光标应该放在哪里
INT 0x10;调用BIOS视频中断
异或ECX,ECX;清除ECX
MOV CX,[msgLen];设置CX=msgLen
MOV-AH,0x0E;我们想在屏幕上打印字符
_循环:
MOV EDX,msgText;将文本地址移动到EDX
DEC-ECX;临时递减ECX
添加EDX、ECX;将ECX添加到msgText的地址
ECX公司;将ECX增加到原来的值
MOV AL,字节[EDX];将EDX处的内存内容放入AL
MOV EDX,msgCol;将文本颜色的地址移到EDX
DEC-ECX;临时递减ECX
添加EDX、ECX;将ECX添加到msgCol的地址
ECX公司;将ECX增加到原来的值
MOV BL,字节[EDX];将EDX处的内存内容放入BL
INT 0x10;调用BIOS视频中断
循环
RET
现在,我应该可以用
callprint
调用这个

(是的,我知道这是倒排的“你好”,我不担心。我可以把它作为“olleH”存储在内存中,我不在乎——我有更大的问题)

首先,我将
CX
设置为
[msgLen]
的行会导致问题。我不得不对其进行硬编码,以使
CX
等于
0x05
,我不知道为什么

其次,大概是出于同样的原因,当我试图设置颜色代码时,我遇到了与文本长度相同的问题。如果我去掉这些行,只需硬编码MOV BL,0x0C,那么它就可以正常工作

然而奇怪的是,
MOV-DX[msgXY]
部分似乎工作正常

我不能给出任何确切的问题,因为我已经试着通过改变很多东西来解决这个问题好几个小时了,我在这里和那里改变的一些小东西似乎会产生非常不可预测的结果。此外,调用各种BIOS中断似乎会改变一些寄存器,这非常烦人。另外,当我将内容向下推到堆栈上,稍后再将其弹出时,情况就不同了,因此我一直避免使用
push
pop

顺便说一下,在这个阶段我仍然处于实模式x86

我现在做的肯定不会这么难。也许我只需要一杯咖啡。或者一些帮助?:)

首先,您将
msgLen
定义为
db
。当您
mov-cx,[msgLen]
时,将加载两个字节。这是否会导致问题取决于
msgLen
后面的内容(如果有)。将
msgLen
定义为
dw
,或者执行
mov cl,[msgLen]
(因为已清除了高位)

我看不出“第二个”有类似的问题——将一个字节移动到8位寄存器中。在本节中使用32位寄存器似乎很奇怪。“应该”行得通,但会使代码膨胀一点
[dx]
当然不是有效的16位寻址模式-您必须使用
bx
(用于其他目的)、
si
di
。由于您使用的是32位寄存器,
lea-edx、[edx+ecx-1]
应该执行您想要的操作,而不必临时递减和递增
ecx
。(但我认为这无助于解决你的问题)

预计某些BIOS中断会改变寄存器。这是否奇怪取决于哪些中断正在进行。大多数情况下,他们没有。无法
pop
push
ed相同的值是很奇怪的。要么你发现了CPU错误,要么你做错了什么。猜猜哪个更有可能。:)它们是有用的指令,所以不能使用它们是很遗憾的。你没有显示引导扇区的“第一幕”,在那里你初始化
ds
es
并设置一个合理的堆栈-也许有问题

你看过int 10h/13h了吗?我想它会做你想做的(“彩虹”文本)。这是一个奇怪的中断,因为它希望文本地址在
es:bp
中,但很有用。另一种方法是将字符和颜色直接插入B800h:xxxx的“屏幕内存”——一个字节用于字符,一个字节用于颜色

引导扇区的编写并不特别容易。如果你有真正的dos可用(甚至是Dosbox),作为.com文件的一部分“尝试”你的例程可能会有所帮助(调试是可用的)。引导扇区是与dos不同的环境,因此它不会解决所有问题,但可能有助于缩小范围

咖啡可能会有帮助,但主要是。。。勇气

最好的, Frank

您可以使用以下代码:

mov si,msg_text
call print_colored
print_colored:
.loop:
lodsb
cmp al,0
je .done
inc bl
mov ah,0x0E
Int 0x10
jmp .loop
.done:
ret

它可以使您的字符串着色,但这不是您的选择。

谢谢您的建议。到目前为止,我在《第一幕》中没有其他的内容。扇区0上的第一阶段引导加载程序只读取下面的扇区并跳转到它。您在这里看到的代码就是那里的代码(减去一些位)。就在这一点之后,我启用了A20和保护模式,但我甚至还没有考虑堆栈或GDT-对我来说仍然非常复杂。所以。。。ds=?,es=?,ss=?,sp=?不管BIOS把他们留在哪里?这可能在一台特定的机器上工作,但不太可能在“任何机器”上工作。也许这对你的目的不是必要的。我不会太急着去g