Created
December 12, 2017 06:41
-
-
Save iximeow/6411432ea181700416d938bcae2eb962 to your computer and use it in GitHub Desktop.
x86 totally supports read/write to 0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; assemble like `nasm bootloader.asm` (will produce a flat binary output by default) | |
; run like `qemu-system-x86_64 bootloader` | |
[BITS 16] | |
[ORG 7c00h] | |
init: | |
mov cx, 0xB800 | |
mov gs, cx | |
call clr_vga | |
mov si, HELLO | |
call write_str | |
mov si, 0x0000 | |
mov fs, si | |
push ds | |
mov ds, si | |
mov ax, 0x78 | |
mov word [fs:si], ax | |
call write_str | |
mov ax, word [fs:si] | |
pop ds | |
mov si, REALRW | |
call write_str | |
; so we wrote and printed 'x' in real mode.. now to do it in protected mode | |
; load up gdt and switch to protected mode! | |
cli | |
lgdt [gdt_ptr] | |
mov eax, cr0 | |
or al, 1 | |
mov cr0, eax | |
; sti ; commented out because i don't feel like listening to interrupts | |
jmp 0x08:protected_code | |
protected_code: | |
; now some 32bit code... | |
[BITS 32] | |
mov ecx, 0x10 | |
mov ds, ecx | |
mov es, ecx | |
mov fs, ecx | |
mov gs, ecx | |
mov ss, ecx | |
; eax points to cursor loc now... | |
xor eax, eax | |
mov byte [eax], 0x79 ; put a Y there | |
mov al, byte [eax] ; read it back | |
mov edi, dword [CURSOR_LOC] | |
add edi, 0xb8000 | |
stosb ; store al to CURSOR_LOC (write 'y') | |
mov al, 0x07 | |
stosb ; set characteristics | |
mov ecx, PROTEND - PROTRW | |
mov esi, PROTRW | |
protected_mode_write_loop: | |
movsb ; copy string byte to VGA memory | |
stosb ; set its characteristics | |
loop protected_mode_write_loop | |
spin: | |
jmp spin | |
[BITS 16] | |
write_str: | |
push ax | |
push si | |
xor ax, ax | |
write_str_each_char: | |
mov al, byte [si] | |
cmp al, 0 | |
je write_str_done | |
inc si | |
call write_char_default_attr | |
jmp write_str_each_char | |
write_str_done: | |
pop si | |
pop ax | |
ret | |
write_char_default_attr: | |
push bx | |
mov bl, 0x07 | |
jmp write_char_inner | |
write_char: | |
push bx | |
write_char_inner: | |
push di | |
mov di, [CURSOR_LOC] | |
mov byte [gs:di], al | |
inc di | |
mov byte [gs:di], bl | |
inc di | |
mov [CURSOR_LOC], di | |
pop di | |
pop bx | |
ret | |
clr_vga: | |
mov di, 4000 | |
clr_vga_loop: | |
dec di | |
mov byte [gs:di], 0x00 | |
cmp di, 0 | |
jne clr_vga_loop | |
mov word [CURSOR_LOC], 0 | |
ret | |
HELLO: | |
db ':hello:', 0 | |
REALRW: | |
db ':if you saw an x, real mode null write is ok:', 0 | |
PROTRW: | |
db ':if you saw a y, protected mode null write is ok:', 0 | |
PROTEND: | |
CURSOR_LOC: | |
dd 0 | |
gdt_ptr: | |
dw 24 ; 24 byte GDT - two entries, plus null selector, each is 8 bytes, so 3 * 8 | |
dd a_gdt | |
a_gdt: | |
dd 0 | |
dd 0 | |
; gdt entries are dumb and wart-y | |
; code | |
dw 0xffff | |
dw 0 | |
db 0 | |
db 10011010b | |
db 11001111b | |
db 0 | |
; data | |
dw 0xffff | |
dw 0 | |
db 0 | |
db 10010010b | |
db 11001111b | |
db 0 | |
; pad for one sector | |
times 510-($-$$) db 0 | |
db 0x55 | |
db 0xAA |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment