Skip to content

Instantly share code, notes, and snippets.

@matyklug18
Last active November 25, 2021 12:18
Show Gist options
  • Save matyklug18/cd71a3e0175c92646f3fbceee2953711 to your computer and use it in GitHub Desktop.
Save matyklug18/cd71a3e0175c92646f3fbceee2953711 to your computer and use it in GitHub Desktop.
; the bios places the first sector (512 bytes) at 0x7c00
; thus, thats the location of this code
[org 0x7c00]
; set the video mode to
; 80x25 16 color text (CGA,EGA,MCGA,VGA)
; (https://stanislavs.org/helppc/int_10-0.html)
; used for clearing the screen
mov ah, 0x00
mov al, 0x03
int 0x10
; set the base of the stack (bp) to an arbitrary value
mov bp, 0x9000
; set the stack pointer (sp) to the base pointer (bp)
mov sp, bp
; switch to protected mode (32 bits)
call switch_to_pm
; in case something weird goes wrong, loop infinitely
jmp $
; start of the global descriptor table (gdt)
; https://wiki.osdev.org/Global_Descriptor_Table
gdt_start:
; needed 8 bytes of zeroes, as the first segment
dq 0x0000_0000_0000_0000
gdt_code:
; segment length, 1st to 16th
dw 0xffff
; base, 1st to 24th bit
dw 0x0000
db 0x00
; Access Byte
;
; Present: true
; Ring Level: kernel
; Type: code/data
;
; Executable: true
; Allow Lower Rings: disabled
; Readable: true
; Access: 0
db 10011010b
; flags (4 bit) +
; segment length, 17th to 20th
;
; Granuality: page (4kib)
; Size: protected mode (32 bit)
db 11001111b
; base, 25th to 32nd
db 0x00
gdt_data:
; segment length, 1st to 16th
dw 0xffff
; base, 1st to 24th bit
dw 0x0000
db 0x00
; Access Byte
; https://wiki.osdev.org/Global_Descriptor_Table
;
; Present: true
; Ring Level: kernel
; Type: code/data
;
; Executable: false
; Direction: upwards
; Readable: true
; Access: 0
db 10010010b
; flags (4 bit) +
; segment length, 17th to 20th
;
; Granuality: page (4kib)
; Size: protected mode (32 bit)
db 11001111b
; base, 25th to 32nd
db 0x00
gdt_end:
; start of the gdt descriptor
gdt_descriptor:
; size, 16 bit, exclusive (one less than true size)
dw gdt_end - gdt_start - 1
dd gdt_start ; address of the table (32 bit)
; constants containing the offsets
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
; the "function" that switches to protected mode
switch_to_pm:
; disable interrupts
cli
; load the gdt descriptor
lgdt [gdt_descriptor]
; set 32-bit mode bit in cr0
; https://wiki.osdev.org/CPU_Registers_x86#CR0
mov eax, cr0
or eax, 0x1
mov cr0, eax
; far jump to the init_pm function in the code segment
; TODO more info
jmp CODE_SEG:init_pm
; switch the assembler to 32 bits
[bits 32]
init_pm:
; TODO more info
mov ax, DATA_SEG
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
; set the stack at a bigger arbitrary value
mov ebp, 0x90000
mov esp, ebp
; call the actual code
call BEGIN_PM
BEGIN_PM:
; insert the c code
incbin './main-c.bin'
; infinite loop
jmp $
; padding
; 512 - magic number = 510
; $ = current address
; $$ = beginning of file address
times 510-($-$$) db 0
; magic number
dw 0xaa55
int main() {
char* video_memory = (char*) 0xb8000;
*video_memory = 'X';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment