I have a 16-bit assembly program (NASM) that changes to VGA graphics mode and tries to fill the entire screen with a solid color, but i can only fill up to 32767 (0x7fff) pixels (instead of the full 320x200 display which is 64000 (0xfa00) pixels), any more and the all the white pixels disappear for some reason. I'm assuming it's some sort of signed increment, but I'm not too sure since I'm still learning a bit. Otherwise, the pixels can show up and get drawn to the screen (i use QEMU)
init.asm:
org 0h
bits 16
%define ENDL 0dh, 0ah
jmp _entry
_entry:
push msg_hello
call puts
jmp entry
entry:
call toggle_vga
push 0fh
push 07fffh
call fill_screen
jmp endp
toggle_vga:
push ax
mov ah, 0fh
mov al, 0h
int 10h
cmp al, 13h
je .toggle_vga_off
jne .toggle_vga_on
.toggle_vga_on:
mov ah, 00h
mov al, 13h
int 10h
jmp .toggle_vga_end
.toggle_vga_off:
mov ah, 00h
mov al, 03h
int 10h
jmp .toggle_vga_end
.toggle_vga_end:
pop ax
ret
fill_screen:
push bp
mov bp, sp
push es
push ax
push dx
push cx
push di
mov ax, 0a000h
mov es, ax
mov dl, [bp + 6]
mov cx, [bp + 4]
mov di, 0
.fill_screen_loop:
cmp di, cx
jge .fill_screen_done
mov [es:di], dx
inc di
jmp .fill_screen_loop
.fill_screen_done:
pop di
pop cx
pop dx
pop ax
pop es
pop bp
ret
puts:
push bp
mov bp, sp
push bx
push ax
mov bx, [bp + 4]
.puts_loop:
cmp byte [bx], 0
je .puts_done
mov ah, 0eh
mov al, [bx]
int 10h
inc bx
jmp .puts_loop
.puts_done:
pop ax
pop bx
pop bp
ret
endp:
cli
hlt
msg_hello: db 'init: loaded successfully.', ENDL, 0
jge .fill_screen_donejumps based on the inequality between signed values. For purposes of signed two's-complement arithmetic,0xfa00is the number -1536. The values 0 through 0x7fff are positive, and so whilediis in this range, we do havedi >= cxand so the loop continues. But then you increment to0x8000, which in signed arithmetic is -32768, and the condition is no longer true.You want to use
jae .fill_screen_donewhich jumps based on the inequality between unsigned values. (There's more info in this answer; I seem to recall an even better one somewhere but I can't find it now.) Or even justje .fill_screen_done; you incrementdiby one on each step, so there is no possibility of it becoming "above" before being equal.Another small bug is
mov [es:di], dx; this stores a word (two bytes) sincedxis a 16-bit register. But you only want to store one byte fromdl(you have leftdhuninitialized), so make itmov [es:di], dl.You could make this more efficient by duplicating the byte into both halves of
dx(mov dh, dl), then storing a word at a time (mov [es:di], dx) and incrementingdiby two (add di, 2, orinc ditwice). Make sure thatcxis always an even number.Better still would be to use
rep stosw, which I'll let you research on your own.