Why does this text from my bootloader blink on real hardware but does not on QEMU?

Programming, for all ages and all languages.
Post Reply
lakroh
Posts: 2
Joined: Tue Oct 08, 2024 7:23 am

Why does this text from my bootloader blink on real hardware but does not on QEMU?

Post by lakroh »

I am writing a simple 16-bit real mode bootloader tic-tac-toe game.

I have a "Draw!!" message which gets printed with black color and yellow background. While on QEMU, this text gets printed without the text itself blinking (intended), but on running it on real hardware after `dd` 'ing the flat binary to a USB drive, the text itself is printed and in correct colors, but is also blinking (not-intended).

Please help me find out why is this so. Here are the relevant parts of the code:

Code: Select all


;* COLORS:
%define black           00h
%define blue            01h
%define green           02h
%define cyan            03h
%define red             04h
%define magenta         05h
%define brown           06h
%define light_gray      07h
%define dark_gray       08h
%define light_blue      09h
%define light_green     0Ah
%define light_cyan      0Bh
%define light_red       0Ch
%define light_magenta   0Dh
%define yellow          0Eh
%define white           0Fh

%define color(fore, back) (((back)<<4) | (fore))


;* gotoxy ----------------------------------------------------------------------------------
;? parameters: dh - row; dl - column
gotoxy:
    mov bh, 0 ; page number (we are using 1 page only currently)
    mov ah, 2 ; set cursor position
    int 10h ; video interrupt
    ret

;* printc ----------------------------------------------------------------------------------
;? Parameters: al - input char, bl - color
printc: ; prints char at crr cursor position
    mov bh, 0 ; page number
    mov cx, 1 ; number of times to write char
    mov ah, 09h ; tells the interrupt call to print character stored in al to screen
    int 10h ; interrupt for video functions - currently printing char
    ret

;* get_cursor_pos --------------------------------------------------------------------------
;? Returns: dh - row, dl = column
get_cursor_pos:
    xor bh, bh ; page number
    mov ah, 03h ; get current cursor pos and size
    int 10h
    ret

;* increment_cursor_pos --------------------------------------------------------------------
; moves cursor to next char, going to next line if required (but never scrolls)
increment_cursor_pos:
    call get_cursor_pos ; dh=row, dl=column

    inc dl

    cmp dl, scr_horiz_char_count ; the cursor should go to next line if equal
    je _increment_cursor_pos_next_line

    jmp _increment_cursor_pos_next_end

_increment_cursor_pos_next_line:
    cmp dh, scr_vert_char_count-1 ; if equal, then can't go next line
    je _increment_cursor_pos_next_end

    inc dh ; otherwise go to next line
    xor dl, dl

_increment_cursor_pos_next_end:
    call gotoxy
    ret

;* prints ----------------------------------------------------------------------------------
;? Parameters: si - input string, bl - color
prints: ; prints string
_prints_loop:
    lodsb ; loads byte at ds:si to al and increments si
    
    cmp al, 0 ; true if the string in si has ended
    je _prints_end

    call printc
    call increment_cursor_pos
    
    jmp _prints_loop
_prints_end:
    ret ; return the control flow

%define draw_msg_color  color(black, yellow)
%define end_msg_row     crr_turn_msg_pos_y
%define end_msg_col     crr_turn_msg_pos_x

%define invert_color(color) (((color & 0xF0)>>4) | ((color & 0x0F)<<4))

draw_msg: db  "     Draw!!    ", 0 ; space padded to overwrite the crr turn msg on screen
o_won_msg: db "    O won!!    ", 0
x_won_msg: db "    X won!!    ", 0

;? Parameters: al - one of the 3 game_state_draw, game_state_*_running
print_end_msg:
    mov dh, end_msg_row ; the position remains same for every case
    mov dl, end_msg_col
    call gotoxy

    cmp al, game_state_draw
    je _print_end_msg_draw
    cmp al, game_state_x_won
    je _print_end_msg_x_won
    cmp al, game_state_o_won
    je _print_end_msg_o_won

_print_end_msg_draw:
    mov si, draw_msg
    mov bl, draw_msg_color
    call prints
    ret

_print_end_msg_x_won:
    mov si, x_won_msg
    mov bl, invert_color(x_player_color)
    call prints
    ret

_print_end_msg_o_won:
    mov si, o_won_msg
    mov bl, invert_color(o_player_color)
    call prints
    ret
Basically, the "X won!!" and "O won!!" messages are printed same as in QEMU; but the "Draw!!" message appears to be blinking on real hardware but not on QEMU (I have also provided some extra code just in case, but the exact code for this is the `_print_end_msg_draw` function). Nothing else is blinking except this string only.

What causes this? How can I resolve it?

---

Thank you for your time reading through this! Your help is appreciated :D

Regards
@lakroh
(a beginner)
lakroh
Posts: 2
Joined: Tue Oct 08, 2024 7:23 am

Re: Why does this text from my bootloader blink on real hardware but does not on QEMU?

Post by lakroh »

Thanks for your response! I got my answer :D.

EXPLANATION:

I was following https://yassinebridi.github.io/asm-docs ... tml#attrib, according to which bits 0-3 are foreground colors and 4-7 are background colors.

It never actually gave the information about "Bits 0-2 are the Foreground Color, Bit 3 is the Foreground Intensity, Bits 4-6 are the Background Color, and Bit 7 is special.". So, now I know that the "light" colors it was listing were just the same 8 colors with higher intensity.

And since I had not set the functionality of 7th special bit to be color intensity instead of background blinking, the color "yellow" for background (making the 7th bit on), turned on the background blinking instead of increasing the intensity.

Basically, I needed to also do this at the beginning of the execution of program https://yassinebridi.github.io/asm-docs ... t10h_1003h
Octocontrabass
Member
Member
Posts: 5452
Joined: Mon Mar 25, 2013 7:01 pm

Re: Why does this text from my bootloader blink on real hardware but does not on QEMU?

Post by Octocontrabass »

You can use INT 0x10 AX=0x1003 BL=0x00 to disable blinking.

I'm not sure why the colors are correct, though. You should see incorrect (too dark) background colors in areas where the text is blinking.

Edit: ah, and I somehow managed to miss your post as I was writing mine.
Post Reply