TASM 1.4 - 显示特定的彩色字符串?

时间:2015-09-17 15:08:05

标签: assembly text colors tasm

我正在使用TASM 1.4而我正在尝试制作一个输出,它将显示不同颜色的句子,所有这些都在同一个屏幕上。我可以制作一些显示彩色文字的东西,但这些文字都有相同的颜色。如何制作显示不同颜色的字符串/句子的内容? 例如,像:

Hi, what group would you like to join?
The Founders
The Vox Populi

“你好,你想加入哪个团体?”绿色的。 “创始人”呈蓝色。并且“The Vox Populi”红色,也许我想要另一个眨眼的句子?我只能将它们全部显示为蓝色或红色或绿色。有帮助吗? 感谢。

2 个答案:

答案 0 :(得分:4)

我将提供一种通过DOS int 21h实现此目的的方法。

原始海报说他们正在使用TASM 1.4(TASM安装程序),这是一个基于DOSBox的环境,带有TASM 3.0和Turbo Debugger 3.1。在DOS时代,有一个视频控制台驱动程序可以使用CONFIG.SYS之类的命令添加到DEVICE=C:\DOS\ANSI.SYS。此驱动程序增强了DOS int 21h输出,因此您可以指定属性(背景颜色,前景色,闪烁);清除屏幕;重置为默认值(通常为黑色)。 DOSBox内置了ANSI.SYS的部分实现。以下代码利用了这些ANSI codes

.model small
.stack 100h

.data
a_cls        db 27, "[2J$"    ; Clear entire screen in currently set attributes
a_reset      db 27, "[0m$"    ; Reset attributes to standard (black on white)
a_blink      db 27, "[5m$"    ; Characters blink (blink doesn't work in all environments)
a_bright     db 27, "[1m$"    ; Bright colored characters
a_dim        db 27, "[2m$"    ; Dim colored characters
a_fg_black   db 27, "[30m$"   ; Foreground colors
a_fg_red     db 27, "[31m$"
a_fg_green   db 27, "[32m$"
a_fg_yellow  db 27, "[33m$"
a_fg_blue    db 27, "[34m$"
a_fg_magenta db 27, "[35m$"
a_fg_cyan    db 27, "[36m$"
a_fg_white   db 27, "[37m$"
a_bg_black   db 27, "[40m$"   ; Background colors
a_bg_red     db 27, "[41m$"
a_bg_green   db 27, "[42m$"
a_bg_yellow  db 27, "[43m$"
a_bg_blue    db 27, "[44m$"
a_bg_magenta db 27, "[45m$"
a_bg_cyan    db 27, "[46m$"
a_bg_white   db 27, "[47m$"

text1        db "Blinking Bright Yellow on Blue$"
text2        db " Back to Normal$" 
text3        db " Bright Yellow on Black$"
combined     db 27, "[0;5;2;31;42m Blinking Dim Red on Green$" 

.code
begin:  
    mov ax,@data
    mov ds,ax
    mov es,ax
    mov ah,09h
    lea dx,a_cls      ; clear screen
    int 21h           
    lea dx,a_bright   ; Bright colored characters
    int 21h
    lea dx,a_blink    ; make the characters blink (if supported)
    int 21h
    lea dx,a_fg_yellow; make the characters yellow
    int 21h
    lea dx,a_bg_blue  ; blue background for characters
    int 21h
    lea dx,text1      ; print text
    int 21h
    lea dx,a_reset    ; reset to defaults 
    int 21h
    lea dx,text2      ; print normal text 
    int 21h
    lea dx,a_bright   ; bright characters
    int 21h
    lea dx,a_fg_yellow; make the characters yellow
    int 21h
    lea dx,text3      ; print text
    int 21h
    lea dx,combined   ; print combined text
    int 21h
    lea dx,a_reset    ; reset to defaults before exiting back to DOS prompt
    int 21h
    .exit
end begin

在DOS中, ANSI 代码以 ESCAPE 字符(十进制27)开头,后跟 [(左括号)。对于属性,可以使用 m 命令。属性可以用分号分隔。除了 m 之外还有其他一些命令,它们可以在ANSI specs中找到。如果您查看上面的代码,您将看到我在哪些地方打破了原始海报可能感兴趣的许多命令的ANSI代码。

以下代码是组合多个属性(使用ANSI)而不是单独执行它们的示例。

combined     db 27, "[0;5;2;31;42mBlinking Dim Red on Green$"

我们从 ESCAPE [开始。 0 将当前属性重置为默认值(大多数硬件在黑色时为白色)。其余属性由 SEMI COLONS 分隔。下一个属性 5 闪烁,下一个是 2 ,颜色变暗, 31 是前景色红色, 42 是绿色背景,后跟命令 m m 结束命令,之后的字符是要打印的文本。

根据前面代码中的转义序列,以下内容将满足海报提出的具体问题:

.model small
.stack 100h

.data
a_reset      db 27, "[0m$"    ; Reset attributes to standard (black on white)

             ; 13, 10 is carriage return line feed combination(CR/LF)
line1        db 27, "[1;32mHi, what group would you like to join?", 13, 10, "$" 
line2        db 27, "[1;34mThe Founders", 13, 10, "$"
line3        db 27, "[1;31mThe Vox Populi", 13, 10, "$"
line4        db 27, "[1;5;31;47mand maybe I'd want another sentence that blinks?$" 

.code
begin:  
    mov ax,@data
    mov ds,ax
    mov es,ax
    mov ah,09h
    lea dx,line1      ; print line 1 (bright green)
    int 21h
    lea dx,line2      ; print line 2 (bright blue)
    int 21h
    lea dx,line3      ; print line 3 (bright red)
    int 21h
    lea dx,line4      ; print line 4 (blinking bright red on white background)
    int 21h
    lea dx,a_reset    ; reset colors back to default before exiting
    int 21h
    .exit
end begin

已知Blink在DOSBox,VMWare,Bochs中工作,但在emu8086和Windows NT + DOS提示符下不起作用。

在这张海报的前一组评论中,其他related question我确实建议另一种方法是编写一个带字符串的过程或函数,并使用DOS中断和/或BIOS中断来更改字符的属性按字符为基础并将它们显示在屏幕上(同时跟踪光标)。最有效的方法是直接将属性写入视频内存(即0xb000:0)。上面我使用的ANSI.SYS方法是最容易开始的,并且应该在现代版本的DOSBox中默认工作。

答案 1 :(得分:4)

您可以将INT 10h / AH=13h用于此目的:

.MODEL small
.STACK 1000h

.DATA
    msg1 db "Hi, what group would you like to join?", 13, 10
    msg1_len = $ - msg1
    msg2 db "The Founders", 13, 10
    msg2_len = $ - msg2
    msg3 db "The Vox Populi", 13, 10
    msg3_len = $ - msg3
    msg4 db "Blinkers", 13, 10
    msg4_len = $ - msg4

.CODE

main PROC
    mov ax, @data
    mov ds, ax              ; Don't forget to initialize DS!
    mov es, ax              ; Segment needed for Int 10h/AH=13h

    lea bp, msg1            ; ES:BP = Far pointer to string
    mov cx, msg1_len        ; CX = Length of string
    mov bl, 2               ; green (http://stackoverflow.com/q/12556973/3512216)
    call print

    lea bp, msg2            ; ES:BP = Far pointer to string
    mov cx, msg2_len        ; CX = Length of string
    mov bl, 3               ; blue (http://stackoverflow.com/q/12556973/3512216)
    call print

    lea bp, msg3            ; ES:BP = Far pointer to string
    mov cx, msg3_len        ; CX = Length of string
    mov bl, 4               ; red (http://stackoverflow.com/q/12556973/3512216)
    call print

    lea bp, msg4            ; ES:BP = Far pointer to string
    mov cx, msg4_len        ; CX = Length of string
    mov bl, 8Eh             ; blinking yellow (Bit7 set, works at least in DOSBox)
    call print

    mov ax, 4C00h           ; Return 0
    int 21h
main ENDP

print PROC                  ; Arguments:
                            ;   ES:BP   Pointer to string
                            ;   CX      Length of string
                            ;   BL      Attribute (color)

    ; http://www.ctyme.com/intr/rb-0088.htm
    push cx                 ; Save CX (needed for Int 10h/AH=13h below)
    mov ah, 03h             ; VIDEO - GET CURSOR POSITION AND SIZE
    xor bh, bh              ; Page 0
    int 10h                 ; Call Video-BIOS => DX is current cursor position
    pop cx                  ; Restore CX

    ; http://www.ctyme.com/intr/rb-0210.htm
    mov ah, 13h             ; VIDEO - WRITE STRING (AT and later,EGA)
    mov al, 1               ; Mode 1: move cursor
    xor bh, bh              ; Page 0
    int 10h                 ; Call Video-BIOS

    ret
print ENDP

END main