汇编实现彩色字符的显示

编程运行环境

选择DOS方式,但现在一般用win10系统,不能进入DOS,只好安装dosbox代替。将写好的源程序保存为asm文件,打开dosbox编译链接并运行。编译链接程序需另行下载,注意与自己的电脑相对应选择32位或64位。

编程目标

在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串’welcome to masm!’。

相关知识

内存地址空间中,B8000H~BFFFFH共32KB的空间即为80×25彩色字符模式显示缓冲区。写入这个地址空间的内容将会出现在显示器上,显示器可以显示25行,每行80个字符,每个字符可以有256种属性
一个字符在显示缓冲区中要占两个字节,偶地址存放字符,奇地址存放字符的属性。通常情况下,B8000H~B8F9FH中的4000个字节的内容将出现在显示器上。

分析

  1. 需要定义存放字符串的内存空间,我们定义数据段来存放字符串,用BX指向其偏移地址。
  2. 我们需要将数据写入显示缓冲区,要取得其段地址,由上述可知该显示缓冲区的段地址为B800H,用es来存放该段地址。
  3. 显示器上的一行80个字符要对应显示缓冲区的160个字节,则行首的偏移地址从0000H开始每行增加A0H。
  4. 在25行80列屏幕中间显示的是3行16列的字符串,则行的偏移地址从6E0H开始,用BP指向行,增量为A0H;列的偏移地址从40H开始,用SI指向列,增量为2。
  5. 我们不难想到用二重循环来解决这个问题,外层循环3次,内层16次循环,需要注意的是每行显示的属性不同,则在外循环中要改变属性存放在寄存器中。具体见源码注释。

源码示例1

assume cs:code,ds:data,ss:stack
data segment
 db 'welcome to masm!'
data ends

stack segment
 db 10 dup (0)
 dw 02H,24H,71H 	;字符的属性:02H为黑底绿字,24H为绿底红字,71H为白底蓝字
stack ends

code segment
start: mov ax,data
	mov ds,ax

	mov ax,stack
 	mov ss,ax
	mov sp,10 	;将栈顶指向堆栈中存放的字符属性

	mov ax,0b800H
 	mov es,ax  	;将显示缓冲区的段地址送入ES
 	mov bp,6e0H 	;BP用来定位显示的行,初始为第11行(从0行记起)

	;AL作为中间变量存放字符的属性,注意栈操作只能为字型数据

	mov cx,3
	s0: mov dx,cx 	;DX暂存外循环变量的值
 	mov bx,0  	;BX用来定位内存的偏移地址
 	mov si,40H 	;SI用来定位显示的列,初始为第64列(从0列记起)
 	pop ax  	;从堆栈中取得字符属性,AL部分有效

	mov cx,16
	s: mov ah,[bx]
 	mov es:[bp][si],ah 	;存放字符的ASCII码
 	mov es:[bp][si].1,al  	;存放字符的属性
 	inc bx
 	add si,2
	loop s

	add bp,0a0H
 	mov cx,dx 	;DX恢复外循环变量的值
 	loop s0

	mov ax,4c00H
 	int 21H
code ends
end start
  1. 汇编源程序的编码安排很灵活,以上程序可以将显示缓冲区的段与存放属性的段相互换。也可以有完全不同的方式,我们需要程序具有修改自身指令并执行的功能,则可以用到几个转移指令。现在我们利用这一点来修改程序数据,详见如下代码。

源码示例2

assume cs:code,ds:data
data segment
 db 'welcome to masm!'
 db 0   	;定义一个值为0的字节用来结束字符串的读取
data ends

code segment
start: mov ax,data
 mov ds,ax
 mov ax,0b800H
 mov es,ax  	;将显示缓冲区的段地址送入ES
 mov bp,6e0H 	;BP用来定位显示的行,初始为第11行(从0行记起)

 mov al,24H 	;AL作为中间变量存放字符的属性
 ; 字符的属性:02H为黑底绿字,24H为绿底红字,71H为白底蓝字
 mov cx,3
s0: mov dx,cx 	;DX暂存外循环变量的值
 mov bx,0  	;BX用来定位内存的偏移地址
 mov si,40H 	;SI用来定位显示的列,初始为第64列(从0列记起)

s: mov cl,[bx]
 mov ch,0
 jcxz s2  	;CX内容的值为零跳转,不为零则继续向下执行
 mov es:[bp][si],cl   		;存放字符的ASCII码
 mov byte ptr es:[bp][si].1,02H  	;存放字符的属性

s1: inc bx
 add si,2
 jmp short s

t: add bp,0a0H
 mov cx,dx 		;DX恢复外循环变量的值
 loop s0

s2: mov di,offset s1
 dec di
 mov cs:[di],al 	;将AL的内容复制到程序中更改字符属性

 mov al,71H 		;修改AL中存放的属性
 jmp short t
code ends
end start

以上程序不必考虑字符串的长度,仅仅关心结束标记,利用转移指令修改源程序的某个数值,要做到的是精确定位。

运行结果

在这里插入图片描述
编程最重要的还是思想和方法,仔细看这个程序还是有很大缺陷的,关于程序的缺陷以后会详细介绍。

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的两个引用,可以给出两种汇编语言输出彩色的hello world的方法方法一: 引用提供了一个emu8086软件,可以用来学习汇编语言。可以按照以下步骤输出彩色的hello world: 1. 新建文件,选择EXE格式。 2. 在代码中输入以下内容: ``` org 100h mov ah, 0x0E ;设置光标位置 mov bh, 0x00 ;页码 mov bl, 0x0E ;前景色 mov cx, 13 ;字符串长度 mov bp, hello ;字符串地址 loop: mov al, [bp] ;将字符串中的字符读入al int 0x10 ;调用BIOS中断显示字符 inc bp ;指向下一个字符 loop loop ;循环显示 jmp $ ;死循环 hello db 'Hello, world!', 0 ;字符串以0结尾 ``` 3. 点击emulate仿真,即可在emu8086软件中看到彩色的hello world输出。 方法二: 引用[2]提供了另一种汇编语言输出彩色的hello world的方法,可以按照以下步骤实现: 1. 新建文件,将以下代码复制到文件中: ``` ASSUME CS:T17,DS:DATA DATA SEGMENT HELLO DB 'HELLO WORLD!' DATA ENDS T17 SEGMENT START: MOV AX,DATA MOV DS,AX ;字符放入ds MOV CX,12 MOV SI,0 MOV BX,0 S0: ;打印hellow world MOV AL,DS:[BX] MOV AH,02H MOV ES:[SI+00H],AX ADD SI,2 INC BX LOOP S0 MOV CX,68 MOV SI,0 S1: ;其余部分黑色清屏 MOV AX,0 MOV ES:[SI+17H],AX ADD SI,2 LOOP S1 MOV AX,4C00H ;退出 INT 21H T17 ENDS END START ``` 2. 保存文件,使用MASM汇编器进行编译,生成可执行文件。 3. 运行可执行文件,即可在命令行窗口中看到彩色的hello world输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值