I'm working on a little operating system, and I'm running into issues drawing pixels. It seems that no matter what I do, I am unable to get anything to appear. I'm trying to follow along with an article by OSDev Wiki, but so far all that works for me is text outputting.
Here's my assembly bootloader code:
[org 0x7c00]
KERNEL_LOCATION equ 0x1000
mov [BOOT_DISK], dl
xor ax, ax
mov es, ax
mov ds, ax
mov bp, 0x8000
mov sp, bp
mov bx, KERNEL_LOCATION
mov dh, 2
mov ah, 0x02
mov al, dh
mov ch, 0x00
mov dh, 0x00
mov cl, 0x02
mov dl, [BOOT_DISK]
int 0x13
mov ah, 0x0
mov al, 0x3
int 0x10 ; text mode
CODE_SEG equ GDT_code - GDT_start
DATA_SEG equ GDT_data - GDT_start
cli
lgdt [GDT_descriptor]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp CODE_SEG:start_protected_mode
jmp $
BOOT_DISK: db 0
GDT_start:
GDT_null:
dd 0x0
dd 0x0
GDT_code:
dw 0xffff
dw 0x0
db 0x0
db 0b10011010
db 0b11001111
db 0x0
GDT_data:
dw 0xffff
dw 0x0
db 0x0
db 0b10010010
db 0b11001111
db 0x0
GDT_end:
GDT_descriptor:
dw GDT_end - GDT_start - 1
dd GDT_start
[bits 32]
start_protected_mode:
mov ax, DATA_SEG
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000 ; 32 bit stack base pointer
mov esp, ebp
jmp KERNEL_LOCATION
times 510-($-$$) db 0
dw 0xaa55
And here's my C++ kernel code:
void draw_pixel(int pos_x, int pos_y, unsigned char colour)
{
unsigned char* location = (unsigned char*)0xA0000 + 320 * pos_y + pos_x;
*location = colour;
}
void write_string( int colour, const char *string )
{
volatile char *video = (volatile char*)0xB8000;
while( *string != 0 )
{
*video++ = *string++;
*video++ = colour;
}
}
extern "C" void main(){
for(int i = 0; i<10; i++)
{
draw_pixel(i,i,15);
}
write_string(15, "Hellop World");
return;
}
I'm rather new to Assembly, but I assume the issue lies in some incompatibility between my ASM code and my C++ code.
For a bit more context, I'm trying to output to VGA 320x200 with 8 bit color palette.
The assembly code sets mode 0x03 (80x25 Text), you have even commented it as such.
Nowhere does it appear that you are setting mode 0x13 (320x200 256 colour).
Your code is writing to both the text and graphics frame buffer. Only the text framebuffer will be rendered in text mode. You cannot render both text and graphics simultaneously. To render text in a graphics mode, you will have to "draw" it.
To set the VGA mode 13h:
mov ah, 0x00
mov al, 0x13
int 0x10
To "draw" text to the graphics framebuffer, you will need character bitmaps. The simplest solution to that is to use the font tables used for translating ASCII codes to glyphs in text mode. That is described at https://wiki.osdev.org/VGA_Fonts
Note that the BIOS call to switch mode (or indeed any BIOS call) must be done before entering protected mode. BIOS calls, or more particularly software interrupts do not work in protected mode.