I'm using TASM 1.4 and I'm trying to make an output that will display different colored sentences, all in the same screen. I can make something that displays colored texts, but the words all have the same color. How do I make something that displays different colored strings/sentences? For example, something like:
Hi, what group would you like to join?
The Founders
The Vox Populi
With "Hi, what group would you like to join?" colored green. "The Founders" colored blue. And "The Vox Populi" colored red, and maybe I'd want another sentence that blinks? I was only able to display them all blue or red or green. Any help? Thanks.
You can use INT 10h / AH=13h
for that purpose:
.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
I'm going to offer one way of achieving this with DOS int 21h
.
The original poster says they are using TASM 1.4(TASM installer), which is a DOSBox based environment with TASM 3.0 and Turbo Debugger 3.1. In the days of DOS there was a video console driver that could be added to CONFIG.SYS
with a command like DEVICE=C:\DOS\ANSI.SYS
. This driver enhanced DOS int 21h
output so you could specify attributes(background color, foreground color, blinking); clear the screen; reset back to default (usually black on white). DOSBox has a partial implementation of ANSI.SYS built in. The following code takes advantage of these 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
In DOS, ANSI codes start with the ESCAPE character (decimal 27) followed by [ (left bracket). For attributes the m command can be used. Attributes can be separated by semi-colons. There are some other commands besides m and they can be found in the ANSI specs. If you review the code above you'll see where I have broken out the ANSI codes for a number of commands that may be of interest to the original poster.
The following code is an example of combining a number of attributes (using ANSI) rather than doing them separately.
combined db 27, "[0;5;2;31;42mBlinking Dim Red on Green$"
Broken out we start with ESCAPE [ . 0 resets the current attributes to default (most hardware is white on black). The rest of the attributes are separated by SEMI COLONS. The next attribute 5 is blinking, the next is 2 which is dimmed color, 31 is foreground color red, 42 is green background followed by the command m . m ends the command and the characters after are the text to print.
Based on the escape sequences in the previous code, the following would fulfill the specific question the poster asked:
.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
Blinking is known to work in DOSBox, VMWare, Bochs, but doesn't work in emu8086, and Windows NT+ DOS prompt.
In a previous set of comments in this posters other related question I did suggest the alternative is to write a procedure or function that takes a string and uses DOS interrupts and/or BIOS interrupts to change the attributes on a character by character basis and display them to the screen (while keeping track of the cursor). The most efficient way is to directly write the attributes to video memory (ie 0xb000:0). The ANSI.SYS method above I have used is the easiest to get going, and should work by default in modern versions of DOSBox.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With