Search code examples
assemblyx86-16dosmasmtasm

How to change the color attribute to white-on-black


I want to use ah=09h to write a message on screen. But when I clean the screen, the text attribute changes the text to be black-on-black. To which value should I change the cleanscreen proc, so the text will be visible?

proc cleanscreen ; cleans the screen
    push cx bx
    mov cx,2000d
    mov bx,0
    clean:
        mov [WORD ptr es:bx],00 ; the value that should be changed
        add bx, 2
    loop clean
    pop cx bx
    ret
endp cleanscreen    
DATASEG
message db 'GAME OVER$'

    ...

    call cleanscreen
    mov dx, offset message
    mov ah,9h
    int 21h

Solution

  • An error on register preservation

    push cx bx
    ...
    pop cx bx
    ret
    

    The stack is a LIFO structure (LastInFirstOut); What goes on the stack last, must come off first. In your code the BX register got pushed last, therefore it has to come off first using code like pop bx cx.
    If the stack is something that you're not comfortable with yet, I would suggest using the other way of writing this:

    push cx
    push bx
    ...
    pop  bx
    pop  cx
    ret
    

    Using character attributes

    The textscreen that you use, stores 3 pieces of information for every character that it displays.
    For each word in the video memory will the low byte contain the ASCII code of the character, and will the high byte register the character's foreground color in the low nibble and the character's background color in the high nibble.

    FEDCBA9876543210 bitnumber
    ----------------
    bbbbffffAAAAAAAA
    ^   ^   ^
    |   |    \ character code (ASCII)
    |    \ foreground color
     \ background color
    

    An instruction like mov [WORD ptr es:bx],00 that uses the WORD tag, will clear all 3 pieces of information, producing a BlackOnBlack space character. Please note that writing 00 does in no way mean byte and nor does writing 0000 mean word. The size of the operation is defined by the mention of byte ptr or word ptr.

    In a comment of yours beneath my answer to a similar question you yourself suggested a way to clean the screen without touching the color attributes:

      xor  bx, bx
    clean:
      mov  [BYTE ptr es:bx],00  ; Only the ASCII field
      add  bx, 2
      loop clean
    

    In order to change the colors of the screen to WhiteOnBlack (07h) and keeping the existing text, we can use:

      mov  bx, 1
    clean:
      mov  [BYTE ptr es:bx], 07h  ; Only the attribute field
      add  bx, 2
      loop clean
    

    And to restore the screen completely to WhiteOnBlack spaces (0720h), use:

      xor  bx, bx
    clean:
      mov  [WORD ptr es:bx], 0720h  ; ASCII & attribute fields
      add  bx, 2
      loop clean
    

    For BrightWhiteOnBlack use 0F20h.