您的位置:首页 > 其它

不一般的hello world--用汇编语言直接操作视频缓冲区

2010-07-15 23:48 507 查看
最近重新温习了一下丢下多时的汇编,汇编之美在于:只要遵守游戏规则,你就可以无拘无束,天马行空;汇编之丑在于如果不遵守游戏规则,你就寸步难行,焦头烂额。就像下面一个简简单单的hello world,用任何一种高级于汇编的语言,整个程序数行代码搞定,而汇编却暗藏玄机。程序用masm在windows xp sp3下编译,链接,运行通过。

DATAS SEGMENT
STRING DB 'HELLO, WORLD!'
DATAS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS

START:
MOV AX,DATAS
MOV DS,AX

; 调用字符串显示子程序
mov dh, 10 ; 字符串显示在窗口的第10行
mov dl, 30 ; 字符串显示在窗口的第30列
mov cl, 10011010b ; 颜色属性字节格式:7~0位分别对应“BL R G B I R G B”,及“闪烁-背景(RGB)-高亮-前景(RGB)”
mov si, 0 ; 字符串首字符的偏移地址
CALL show_str

; 程序结束
MOV AH,4CH
INT 21H

; 字符串显示子程序
;传入参数:

; 行号 dh

; 列号 dl
; 颜色属性 cl

; 字符串段地址 ds

; 字符串首字符偏移地址 si

; 返回值 无
show_str: MOV AX, 0

; 备份当前寄存器状态
push ax
push bx
push cx
push dx
push si
push es

; 映射显存起始段基地址给es,便于后面存放显示内容
mov ax,0b800h
mov es,ax

; 计算显示字符其实位置相对于es段基地址的偏移量

dec dh ; 行号从0开始,显示在第n行,在代码上其实是第n-1行
mov al,160 ; 每行显示80个字符,每个字符1个字节,字符后面的颜色属性值占1个字节
mul dh ; 行偏移地址
mov bx,ax
dec dl
mov al,2
mul dl ; 列偏移地址
add bx,ax ; 字符串的总偏移地址

mov al,cl
mov ch,0

cpy : mov cl,[si]
jcxz done ; 当字符串全部显示完毕时,退出,此时cx的值为0
mov es:[bx],cl ;显存偶地址存放字符
mov es:[bx+1],al ;显存奇地址存放颜色属性
add bx,2
inc si
jmp short cpy

done: pop es ; 还原寄存器状态
pop si
pop dx
pop cx
pop bx
pop ax
ret

CODES ENDS
END START

程序的基本逻辑在于两点:

1,计算机系统中,设备内存(如BIOS,显存,各种输入输出设备的缓存)虽然在物理上是独立的,但是在逻辑上都映射在系统内存的地址空间上,CPU在某个存储器地址上进行读写操作,实际上是直接对该地址所映射的物理存储器上进行读写操作。因此,要在屏幕上显示字符串,只要把字符串复制到显存所在的地址空间区域就可以了。

2,在显存中,单个ascii码字符显示需要2个字节,偶数位上的字节是字符本身,后面紧跟的奇数位上保存颜色属性值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: