TASM 1.4 - Changing background color without clearing the screen?
Asked Answered
I

1

1

I'm using Tasm 1.4. I'm trying to change the color of the background and text without clearing the previous text, but it always ends up on clearing the previous text although the colors are changed.

For example:

mov ah,09h
lea dx,text1
int 21h             ;displays text1
mov ah,01h
int 21h             ;I input a character
mov ah,06h
mov bh,42h
mov cx,0000h
mov dx,184fh
int 10h             ;I use this to change the text and background color
mov ah,02h
mov bh,00h
mov dh,0ch
mov dl,20h
int 10h             ;along with this
mov ah,09h
lea dx,text2
int 21h             ;displays text2
mov ah,02h
mov dl,al
int 21h             ;displays the inputted character

Now what happens there is...

  • it displays text1
  • it asks for an input
  • I enter an input
  • it will display text2 followed by the inputted character, with the background color changed to red and the text color changed to green. But, text1 was cleared from the screen.

I should also say that text1 and text2 can definitely fit in the same screen.

So how do I get the same output but with text1 not being cleared from the screen?

Innermost answered 16/9, 2015 at 21:41 Comment(16)
hi! thanks. edited. :)Innermost
Do you want to clear the entire screen with that color? By scrolling that is what will happen. But I'm unsure what you want the output to be like.Anastigmatic
hi! thanks. I actually don't want to clear the entire screen with the color, but rather, just change the background and text colors without clearing the screen.Innermost
So you really only want what is in text2 followed by the character that was typed to be displayed in the new color scheme.Anastigmatic
I also want text1 to remain on the screen, followed by text2 and the character that was typed, all displayed in the new color scheme. :)Innermost
Unfortunately you are going to have to loop through text2 string manually character by character and display each character at the proper location. The brute force method would be to get the position of the cursor before starting to print any text. Use int 10h/ah-9 to write each character and manually advance the cursor to the next column. There is another way to do this if ANSI.SYS console driver is used.Anastigmatic
oh, I see..well unfortunately, I won't be able to do it manually character by character because this goes all the way to text18, with each text having quite a lot of characters. I guess I'll just have to deal with it. Anyways, thanks for the help. :)Innermost
You could write a subroutine/function that writes a string (or character) in a particular color combination.Anastigmatic
um, how? sorry, I really don't knowInnermost
You could read about PROC in the TASM manual.Anastigmatic
Yeah I see that PROC thing a lot, I guess I should be using it a lot more. Will read, thanks. :)Innermost
@MichaelPetch: tagging you since you seem to understand this question. Is there a tag for questions like this about programs that use whatever API this is using to do full-screen text and keyboard input? They're often written and tagged as if this is the only use for x86 asm, so it sometimes takes some reading to figure out that they're not writing a normal modern program in asm. Is this a DOS API? Or does it work with just the BIOS, with no O/S booted yet? I'd love it if questions like this would at least start with "In this 16bit DOS program..." or whatever context it actually is.Hornback
@PeterCordes: A lot of these type of questions are poorly tagged, or don't come out and say what the environment is in the description. I only know because int 21h is generally a DOS interrupt (so they are running on some form of DOS) so there is an OS present. There are tags 16-bit and DOS that could help clarify questions like this. There is a tag bare-metal for environments without an OS (so you are limited to the BIOS calls)Anastigmatic
@MichaelPetch: So int 21h requires DOS, not just BIOS? Thanks, now I'll know what to look for.Hornback
@PeterCordes Correct if you see int 21h then it is definitely not bare-metal (no OS), DOS or a DOS emulation layer must be present. In 32 bit Windows environments that still support 16bit code you are able to use int 21h and many BIOS calls that don't pose a security threat (BIOS calls that read the hard disk will not return data). BIOS calls under a Windows NT(or higher) command prompt are emulated. Most BIOS calls are not available in protected-mode. BIOS calls don't rely on an OS.Anastigmatic
@PeterCordes And to be complete, most of the BIOS software interrupts (no OS needed) are: int 05h,int 10h,int 13h,int 14h,int 15h,int 16h,int 17h,int 1Ah,int 1Bh,int 1Ch,int 1Dh,int 1Eh,int 1Fh,int 41h,int 46h,int 4Ah . There are a few very uncommon ones for specific hardware but you likely won't see them.Anastigmatic
L
2

Just write to the video memory directly and be done with it. If you're in mode 03h, then you've got 80x25 chars on screen. Each char has 16bits associated with it. 8 bits for text/background colour and another 8 for the character displayed.

The character to display is the first byte and the attributes are the second byte. You can find a brief description of the memory organization and attribute bits here: http://www.shikadi.net/moddingwiki/B800_Text

Here's some code that will leave the text content unchanged and will just set the attribute byte for all text on an 80x25 screen. I use nasm these days, it's been 15 years since I last used tasm - I'm not sure if any of the syntax will need changing.

;********************************************************
; Sets the text-mode attributes for the whole 80x25 screen
; call  with AL = attribute (hi nibble = background, lo-nibble = foreground)
;********************************************************
setTextAttributes:
    push    es              ; save the seg register
    mov     cx, 80*25       ; # of chars to do
    mov     bx, 0xB800      ; segment of the screen memory for this video mode
    mov     es, bx
    xor     di, di          ; point to char data of screen-pos 0,0
.setTextAttributesLoop:
    inc     di              ; advance by 1 to point to the attribute, rather than the char
    stosb                   ; store our attribute byte to [es:di] and increment di. di now points to a character
    loop    .setTextAttributesLoop
    pop     es
    ret
Lunate answered 21/9, 2015 at 2:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.