-OBJS = main.o framebuffer.o memory.o
-DEV=/dev/sdb
+STAGE3 = stage3/main.o stage3/framebuffer.o stage3/memory.o stage3/paging.o
nyax.img: stage1.out stage2.out stage3.out
cat stage{1,2,3}.out > nyax.img
-stage1.out: mbr.asm stage2.out stage3.out
- nasm -f bin mbr.asm -o stage1.out \
+stage1.out: stage1/main.asm stage1/print.asm stage2.out stage3.out
+ nasm -f bin stage1/main.asm -o stage1.out \
-dKSIZE=$$(du -cb stage{2,3}.out | tail -n1 | cut -f1)
-stage2.out: setup.asm
- nasm -f bin setup.asm -o stage2.out
+stage2.out: stage2/main.asm stage2/mmap.asm stage2/paging.asm stage2/vesa.asm stage1/print.asm
+ nasm -f bin stage2/main.asm -o stage2.out
-stage3.out: $(OBJS) stage2.out
- ld -o stage3.out --oformat binary $(OBJS) \
+stage3.out: $(STAGE3) stage2.out
+ ld -o stage3.out --oformat binary $(STAGE3) \
-Ttext $$(printf "%x\n" $$(echo $$(du -b stage2.out | cut -f1)+32256 | bc))
-%.o: %.asm
+stage3/%.o: stage3/%.asm
nasm -f elf64 $< -o $@
-.PHONY: run
+.PHONY: run clean flash
+
run: nyax.img
bochs -q
-.PHONY: clean
clean:
- rm -rf *.o *.out *.img
+ rm -rf stage3/*.o *.out *.img
flash: nyax.img
- dd if=./nyax.img of=$(DEV)
+ dd if=nyax.img of=$(DEV)
+++ /dev/null
-; uses eax, ebx
-print_str:
- mov ah, 0x0E
-.print:
- mov al, [ebx]
- cmp al, 0
- je .return
- int 0x10
- inc ebx
- jmp .print
-.return:
- ret
+++ /dev/null
-%define COLOR_BLACK 0
-%define COLOR_BLUE 1
-%define COLOR_GREEN 2
-%define COLOR_CYAN 3
-%define COLOR_RED 4
-%define COLOR_MAGENTA 5
-%define COLOR_BROWN 6
-%define COLOR_LIGHT_GREY 7
-%define COLOR_DARK_GREY 8
-%define COLOR_LIGHT_BLUE 9
-%define COLOR_LIGHT_GREEN 10
-%define COLOR_LIGHT_CYAN 11
-%define COLOR_LIGHT_RED 12
-%define COLOR_LIGHT_MAGENTA 13
-%define COLOR_LIGHT_BROWN 14
-%define COLOR_WHITE 15
+++ /dev/null
-%include "colors.asm"
-global print_chr, print_str, print_num, clear_screen
-extern memcpy
-
-section .data
-
-pos:
-.row: db 0
-.col: db 0
-
-cursor: dq 0xB8000
-color: db COLOR_WHITE | (COLOR_BLACK << 4)
-
-section .text
-
-set_color:
- shl sil, 4
- add dil, sil
- mov [color], dil
-
-update_cursor:
- mov rbx, [cursor]
- sub rbx, 0xB8000
- shr rbx, 1
-
- mov dx, 0x3D4
- mov al, 14
- out dx, al
-
- mov dx, 0x3D5
- mov al, bh
- out dx, al
-
- mov dx, 0x3D4
- mov al, 15
- out dx, al
-
- mov dx, 0x3D5
- mov al, bl
- out dx, al
-
- ret
-
-set_chr:
- mov rax, [cursor]
- mov byte[rax], dil
- inc rax
- mov dil, [color]
- mov [rax], dil
- inc rax
- mov [cursor], rax
- jmp update_cursor
-
-vertical_tab:
- mov al, [pos.row]
- inc al
- cmp al, 25
- je .scroll
- mov [pos.row], al
- mov rax, [cursor]
- add rax, 160
- mov [cursor], rax
- jmp update_cursor
-.scroll:
- mov rdi, 0xB8000
- mov rsi, 0xB80A0
- mov rdx, 0xF00
- jmp memcpy
-
-carriage_return:
- mov rax, [cursor]
- xor rbx, rbx
- mov bl, [pos.col]
- shl bl, 1
- sub rax, rbx
- mov [cursor], rax
- mov byte[pos.col], 0
- jmp update_cursor
-
-newline:
- call vertical_tab
- jmp carriage_return
-
-print_chr:
- cmp dil, 10
- je newline
- cmp dil, 11
- je vertical_tab
- cmp dil, 13
- je carriage_return
- mov al, [pos.col]
- inc al
- cmp al, 80
- je .newline
- mov [pos.col], al
- jmp set_chr
-.newline:
- push rdi
- call newline
- pop rdi
- jmp set_chr
-
-print_str:
- mov rax, rdi
-.print:
- mov dil, [rax]
- cmp dil, 0
- je .return
- push rax
- call print_chr
- pop rax
- inc rax
- jmp .print
-.return:
- ret
-
-print_num:
- mov rax, rdi
- mov r10, 10
- xor rcx, rcx
-.convert:
- inc rcx
- xor rdx, rdx
- div r10
- add dl, '0'
- push rdx
- cmp rax, 0
- jne .convert
-.print:
- cmp rcx, 0
- je .return
- dec rcx
- pop rdi
- push rcx
- call print_chr
- pop rcx
- jmp .print
-.return:
- ret
-
-clear_screen:
- mov qword[cursor], 0xB8000
-.clr:
- cmp qword[cursor], 0xB8FA0
- je .return
- mov dil, ' '
- call set_chr
- jmp .clr
-.return:
- mov qword[cursor], 0xB8000
- mov byte[pos.row], 0
- mov byte[pos.col], 0
- jmp update_cursor
+++ /dev/null
-global _start
-extern print_str, print_num, print_chr, clear_screen
-
-section .data
-
-headline: db "nyax stage3", 10, 10, 0
-
-disclaimer: db \
- "NyaX", 10, \
- "(C) 2022 Flecken-chan", 10, \
- "Dis progwam comes with ABSOLUTELY NO WAWWANTY", 10, \
- "Dis iz fwee software, and your'e welcome to redistwibute it", 10, " under certain conditions", 10, 0
-
-section .text
-
-_start:
- call clear_screen
-
- mov rdi, headline
- call print_str
-
- mov rdi, disclaimer
- call print_str
-
- xor rdi, rdi
- .loop:
- push rdi
- mov dil, 13
- call print_chr
- mov rdi, [rsp]
- call print_num
- pop rdi
- inc rdi
- jmp .loop
+++ /dev/null
-[org 0x7C00]
-
-%define KSTART 0x7E00
-%define KSECTORS (KSIZE + 511) / 512
-
-boot:
- ; init segment registers
- xor ax, ax
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
-
- ; init stack
- mov bp, KSTART ; stack grows down, overwriting MBR
- mov sp, bp
-
- ; print message
- mov ebx, .msg
- call print_str
-
- ; load stage2 and stage3
- call load_stages
-
- ; jump into stage2
- jmp KSTART
-
-.msg: db 10, 13, "nyax stage1", 10, 13, 0
-
-
-load_stages:
- mov ebx, .msg
- call print_str
-
- mov ah, 0x02 ; read sectors from drive
- mov al, KSECTORS ; number of sectors
- xor ch, ch ; cylinder=0
- mov cl, 2 ; sector=2
- xor dh, dh ; head=0
- mov bx, KSTART ; buffer
- int 0x13
- jc .fail ; CF set on error
- cmp al, KSECTORS ; check read sectors count
- jne .fail
-
- ret
-
-.fail:
- mov ebx, .fail_msg
- call print_str
- jmp $
-
-.msg: db "loading stage2 and stage3 from disk", 10, 13, 0
-.fail_msg: db "disk failure, try rebooting", 10, 13, 0
-
-
-%include "bios_print.asm"
-
-times 510-($-$$) db 0
-dw 0xAA55
+++ /dev/null
-global memcpy, memmove
-
-section .text
-
-memcpy:
-.bulk_copy:
- cmp rdx, 8
- jl .bytewise_copy
- mov rax, qword[rsi]
- mov qword[rdi], rax
- sub rdx, 8
- add rdi, 8
- add rsi, 8
-.bytewise_copy:
- cmp rdx, 0
- je .return
- mov al, byte[rsi]
- mov byte[rdi], al
- dec rdx
- inc rdi
- inc rsi
- jmp .bytewise_copy
-.return:
- ret
-
-memmove:
- mov rcx, rdx
-.bulk_read:
- cmp rdx, 8
- jl .bytewise_read
- push qword[rsi]
- add rsi, 8
- sub rdx, 8
- jmp .bulk_read
-.bytewise_read:
- cmp rdx, 0
- je .bulk_write
- dec rsp
- mov al, byte[rsi]
- mov byte[rsp], al
- inc rsi
- dec rdx
- jmp .bytewise_read
-.bulk_write:
- cmp rcx, 8
- jl .bytewise_write
- pop qword[rdi]
- add rdi, 8
- sub rcx, 8
-.bytewise_write:
- cmp rcx, 0
- je .return
- mov al, byte[rsp]
- mov byte[rdi], al
- inc rsp
- inc rdi
- dec rcx
-.return:
- ret
+++ /dev/null
-[org 0x7E00]
-
-%define PAGETABLE 0x1000
-%define VESAINFO 0x0500
-%define VESAMODE VESAINFO+512
-%define OWNMODE VESAMODE+256
-%define GFXINFO 0x500
-
-setup:
- ; print message
- mov ebx, .msg
- call print_str
-
- ; setup VESA
- call vesa
-
- ; get extended memory map
- call mmap
-
- ; build page table
- call paging
-
- ; jump into long mode
- jmp 0x0008:long_mode
-
-.msg:
- db 10, 13, "nyax stage2", 10, 13, 0
-
-
-vesa:
- ; print message
- mov ebx, .msg
- call print_str
-
- ; get vesa bios info
- mov eax, dword[.vbe2]
- mov dword[VESAINFO], eax ; move "VBE2" to start of vesainfo struct
- mov ax, 0x4F00 ; get VESA BIOS information
- mov di, VESAINFO ; struct buffer
- int 0x10
-
- cmp ax, 0x004F ; check ax for correct magic number
- jne .fail_getinfo
-
- mov eax, dword[.vesa]
- cmp dword[VESAINFO], eax ; check if "VESA" is at start of stuct
- jne .fail_getinfo
-
- ; print select message
- mov ebx, .select_msg
- call print_str
-
- ; get segment:offset pointer to video modes into gs:ebx
- movzx ebx, word[VESAINFO+14]
- mov ax, word[VESAINFO+16]
- mov gs, ax
-
- ; convert modes to own structure
-
- xor esi, esi ; number of avail modes
-
-.mode_loop:
- ; get mode info
- mov cx, [gs:ebx] ; video mode into cx
- cmp cx, 0xFFFF ; 0xFFFF is terminator, no suitable mode has been found
- je .mode_done
- mov ax, 0x4F01 ; get VESA mode information
- mov di, VESAMODE ; vesa mode info struct buffer
- int 0x10
-
- cmp ax, 0x004F ; check ax for correct magic number
- jne .fail_modeinfo
-
- mov al, byte[VESAMODE] ; get attributes
- and al, 0b10000000 ; extract bit 7, indicates linear framebuffer support
- jz .mode_next
-
- mov al, byte[VESAMODE+25] ; get bpp (bits per pixel)
- cmp al, 32
- jne .mode_next
-
- push ebx ; print_num and print_str modify ebx
-
- mov eax, esi
- mov ebx, 12
- mul ebx
- mov edi, eax
- add edi, OWNMODE
-
- mov [edi+10], cx ; copy mode
-
- mov eax, edi
- call print_num
-
- ; print selector
- mov al, '['
- call print_chr
-
- mov eax, esi
- add eax, 'a'
- call print_chr
-
- mov al, ']'
- call print_chr
-
- mov al, ' '
- call print_chr
-
- mov ax, [VESAMODE+16] ; copy pitch
- mov [edi+0], ax
-
- movzx eax, word[VESAMODE+18] ; copy width
- mov [edi+2], ax
- call print_num
-
- mov al, 'x'
- call print_chr
-
- movzx eax, word[VESAMODE+20] ; copy height
- mov [edi+4], ax
- call print_num
- call newline
-
- mov eax, [VESAMODE+40] ; copy framebuffer
- mov [edi+6], eax
-
- pop ebx
-
- inc esi
- cmp esi, 'z'-'a' ; only print up to z
- jg .mode_done
-
-.mode_next:
- add ebx, 2 ; increase mode pointer
- jmp .mode_loop ; loop
-
-.mode_done:
- cmp esi, 0
- je .fail_nomode
-
-.input:
- mov ebx, .select_prompt
- call print_str
-
- mov ah, 0x00 ; get keypress, blocking
- int 0x16
-
- call print_chr ; echo user input
-
- movzx edi, al ; backup al
- call newline
-
- sub edi, 'a'
- cmp edi, esi
- jb .valid ; check validity
-
- mov ebx, .invalid
- call print_str
-
- jmp .input
-
-.valid:
- mov eax, edi
- call print_num
- call newline
-
- ; convert selected number to address
- mov eax, edi
- mov ebx, 12
- mul ebx
- add eax, OWNMODE
-
- ; copy to final gfx info location
- mov ebx, [eax]
- mov [GFXINFO], ebx
-
- mov ebx, [eax+4]
- mov [GFXINFO+4], ebx
-
- mov bx, [eax+6]
- mov [GFXINFO+6], bx
-
- ; set mode
- mov bx, [eax+10] ; video mode in bx (first 13 bits)
- or bx, 0b0100000000000000 ; set bit 14: enable linear frame buffer
- and bx, 0b0111111111111111 ; clear deprecated bit 15
- mov ax, 0x4F02 ; set VBE mode
- int 0x10
-
- ret
-
-.msg: db "setting up vesa", 10, 13, 0
-.vbe2: db "VBE2"
-.vesa: db "VESA"
-.select_msg: db "avaliable video modes:", 10, 13, 0
-.select_prompt: db "select video mode: ", 0
-.invalid: db "invalid input", 10, 13, 0
-
-.fail_getinfo:
- mov ebx, .fail_getinfo_msg
- jmp .fail
-
-.fail_modeinfo:
- mov ebx, .fail_modeinfo_msg
- jmp .fail
-
-.fail_nomode:
- mov ebx, .fail_nomode_msg
- jmp .fail
-
-.fail_getinfo_msg: db "failed getting vesa bios info", 10, 13, 0
-.fail_modeinfo_msg: db "failed getting video mode info", 10, 13, 0
-.fail_nomode_msg: db "no suitable video modes available", 10, 13, 0
-
-.fail:
- call print_str
- jmp $
-
-
-mmap:
- mov ebx, .msg
- call print_str
-
- ret
-
-.msg: db "getting extended memory map", 10, 13, 0
-
-
-paging:
- ; print message
- mov ebx, .msg
- call print_str
-
- ; clear 4 levels of page maps
- mov di, PAGETABLE+0x0000
-.clr_buf:
- mov byte[di], 0
- inc di
- cmp di, PAGETABLE+0x4000
- jne .clr_buf
-
- ; init 3 page map levels
- mov dword[PAGETABLE+0x0000], PAGETABLE+0x1003
- mov dword[PAGETABLE+0x1000], PAGETABLE+0x2003
- mov dword[PAGETABLE+0x2000], PAGETABLE+0x3003
-
- ; fill up level 4 page map
- mov eax, 3
- mov di, PAGETABLE+0x3000
-.build_pt:
- mov [di], eax
- add eax, 0x1000
- add di, 8
- cmp eax, 0x100000
- jb .build_pt
-
- ; enable paging and long mode
-
- mov di, PAGETABLE
-
- mov al, 0xFF
- out 0xA1, al
- out 0x21, al
-
- nop
- nop
-
- lidt [.idt]
-
- mov eax, 0b10100000
- mov cr4, eax
-
- mov edx, edi
- mov cr3, edx
-
- mov ecx, 0xC0000080
- rdmsr
-
- or eax, 0x00000100
- wrmsr
-
- mov ebx, cr0
- or ebx, 0x80000001
- mov cr0, ebx
-
- lgdt [.gdt_pointer]
-
- ret
-
-.gdt:
- dq 0
- dq 0x00209A0000000000
- dq 0x0000920000000000
- dw 0
-
-.gdt_pointer:
- dw $ - .gdt - 1
- dd .gdt
-
-.idt:
- dw 0
- dd 0
-
-.msg:
- db "building page table", 10, 13, 0
-
-
-%include "bios_print.asm"
-
-; uses eax, ebx, ecx, edx
-print_num:
- mov ebx, 10
- xor ecx, ecx
-.convert:
- inc ecx
- xor edx, edx
- div ebx
- add dl, '0'
- push dx
- cmp eax, 0
- jne .convert
-.print:
- cmp ecx, 0
- je .return
- dec ecx
- pop ax
- mov ah, 0x0E
- int 0x10
- jmp .print
-.return:
- ret
-
-
-newline:
- mov al, 10
- call print_chr
-
- mov al, 13
- call print_chr
-
- ret
-
-print_chr:
- mov ah, 0x0E
- int 0x10
- ret
-
-[bits 64]
-
-long_mode:
- ; setup segment registers
- mov ax, 0x0010
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
--- /dev/null
+[org 0x7C00]
+
+%define KSTART 0x7E00
+%define KSECTORS (KSIZE + 511) / 512
+
+boot:
+ ; init segment registers
+ xor ax, ax
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ ; init stack
+ mov bp, KSTART ; stack grows down, overwriting MBR
+ mov sp, bp
+
+ ; print message
+ mov ebx, .msg
+ call print_str
+
+ ; load stage2 and stage3
+ call load_stages
+
+ ; jump into stage2
+ jmp KSTART
+
+.msg: db 10, 13, "nyax stage1", 10, 13, 0
+
+
+load_stages:
+ mov ebx, .msg
+ call print_str
+
+ mov ah, 0x02 ; read sectors from drive
+ mov al, KSECTORS ; number of sectors
+ xor ch, ch ; cylinder=0
+ mov cl, 2 ; sector=2
+ xor dh, dh ; head=0
+ mov bx, KSTART ; buffer
+ int 0x13
+ jc .fail ; CF set on error
+ cmp al, KSECTORS ; check read sectors count
+ jne .fail
+
+ ret
+
+.fail:
+ mov ebx, .fail_msg
+ call print_str
+ hlt
+
+.msg: db "loading stage2 and stage3 from disk", 10, 13, 0
+.fail_msg: db "disk failure, try rebooting", 10, 13, 0
+
+%include "stage1/print.asm"
+
+times 510-($-$$) db 0
+dw 0xAA55
--- /dev/null
+; uses eax, ebx
+print_str:
+ mov ah, 0x0E
+.print:
+ mov al, [ebx]
+ cmp al, 0
+ je .return
+ int 0x10
+ inc ebx
+ jmp .print
+.return:
+ ret
--- /dev/null
+[org 0x7E00]
+
+%define PAGETABLE 0x1000
+%define VESAINFO 0x0500
+%define VESAMODE VESAINFO+512
+%define OWNMODE VESAMODE+256
+%define GFXINFO PAGETABLE-10
+%define MEMMAPCNT GFXINFO-2
+%define MEMMAP 0x500
+
+setup:
+ ; print message
+ mov ebx, .msg
+ call print_str
+
+ ; setup VESA
+ ; call vesa
+
+ ; get extended memory map
+ call mmap
+
+ ; build page table
+ call paging
+
+ ; jump into long mode
+ jmp 0x0008:long_mode
+
+.msg:
+ db 10, 13, "nyax stage2", 10, 13, 0
+
+%include "stage2/vesa.asm"
+%include "stage2/mmap.asm"
+%include "stage2/paging.asm"
+%include "stage1/print.asm"
+
+; modify eax, ebx, ecx, edx
+print_hex:
+ mov ebx, 0x10
+ jmp print_num
+print_dec:
+ mov ebx, 10
+print_num:
+ xor ecx, ecx
+.convert:
+ inc ecx
+ xor edx, edx
+ div ebx
+ cmp dl, 10
+ jb .digit
+ add dl, 'A'-10
+ jmp .next
+.digit:
+ add dl, '0'
+.next:
+ push dx
+ cmp eax, 0
+ jne .convert
+.print:
+ cmp ecx, 0
+ je .return
+ dec ecx
+ pop ax
+ mov ah, 0x0E
+ int 0x10
+ jmp .print
+.return:
+ ret
+
+newline:
+ mov al, 10
+ call print_chr
+
+ mov al, 13
+ call print_chr
+
+ ret
+
+print_chr:
+ mov ah, 0x0E
+ int 0x10
+ ret
+
+[bits 64]
+
+long_mode:
+ ; setup segment registers
+ mov ax, 0x0010
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ ; kernel begins here
--- /dev/null
+%define MAPMAGIC 0x534D4150
+
+mmap:
+ mov ebx, .msg
+ call print_str
+
+ xor ebx, ebx ; counter for interrupt
+ mov di, MEMMAP
+
+.loop:
+ ; issue an INT 0x15, EAX = 0xE820 interrupt
+ mov eax, 0xE820
+ mov ecx, 24
+ mov edx, MAPMAGIC
+ int 0x15
+
+ cmp eax, MAPMAGIC ; detect failure
+ jne .fail
+
+ mov eax, [di+16]
+ cmp eax, 2
+ ja .next
+
+ mov eax, [di+4]
+ cmp eax, 0
+ jne .keep
+
+ mov eax, [di+0]
+ cmp eax, 0x100000
+ jb .next
+
+.keep:
+ add di, 24
+
+.next:
+ cmp ebx, 0
+ jne .loop
+
+ mov ax, di
+ sub ax, MEMMAP
+ xor dx, dx
+ mov bx, 24
+ div bx
+ mov [MEMMAPCNT], ax
+
+ mov eax, MEMMAPCNT
+ call print_dec
+ call newline
+ ;jmp $
+
+ ret
+
+.fail:
+ mov ebx, .fail_msg
+ call print_str
+ jmp $
+
+.msg: db "getting extended memory map", 10, 13, 0
+.fail_msg: db "memory map failure", 10, 13, 0
+
--- /dev/null
+paging:
+ ; print message
+ mov ebx, .msg
+ call print_str
+
+ ; clear 4 levels of page maps
+ mov di, PAGETABLE+0x0000
+.clr_buf:
+ mov byte[di], 0
+ inc di
+ cmp di, PAGETABLE+0x4000
+ jne .clr_buf
+
+ ; init 3 page map levels
+ mov dword[PAGETABLE+0x0000], PAGETABLE+0x1003
+ mov dword[PAGETABLE+0x1000], PAGETABLE+0x2003
+ mov dword[PAGETABLE+0x2000], PAGETABLE+0x3003
+
+ ; fill up level 4 page map
+ mov eax, 3
+ mov di, PAGETABLE+0x3000
+.build_pt:
+ mov [di], eax
+ add eax, 0x1000
+ add di, 8
+ cmp eax, 0x100000
+ jb .build_pt
+ ; enable paging and long mode
+
+ mov di, PAGETABLE
+
+ mov al, 0xFF
+ out 0xA1, al
+ out 0x21, al
+
+ nop
+ nop
+
+ lidt [.idt]
+
+ mov eax, 0b10100000
+ mov cr4, eax
+
+ mov edx, edi
+ mov cr3, edx
+
+ mov ecx, 0xC0000080
+ rdmsr
+
+ or eax, 0x00000100
+ wrmsr
+
+ mov ebx, cr0
+ or ebx, 0x80000001
+ mov cr0, ebx
+
+ lgdt [.gdt_pointer]
+
+ ret
+
+.gdt:
+ dq 0
+ dq 0x00209A0000000000
+ dq 0x0000920000000000
+ dw 0
+
+.gdt_pointer:
+ dw $ - .gdt - 1
+ dd .gdt
+
+.idt:
+ dw 0
+ dd 0
+
+.msg:
+ db "building page table", 10, 13, 0
--- /dev/null
+vesa:
+ ; print message
+ mov ebx, .msg
+ call print_str
+
+ ; get vesa bios info
+ mov eax, dword[.vbe2]
+ mov dword[VESAINFO], eax ; move "VBE2" to start of vesainfo struct
+ mov ax, 0x4F00 ; get VESA BIOS information
+ mov di, VESAINFO ; struct buffer
+ int 0x10
+
+ cmp ax, 0x004F ; check ax for correct magic number
+ jne .fail_getinfo
+
+ mov eax, dword[.vesa]
+ cmp dword[VESAINFO], eax ; check if "VESA" is at start of stuct
+ jne .fail_getinfo
+
+ ; print select message
+ mov ebx, .select_msg
+ call print_str
+
+ ; get segment:offset pointer to video modes into gs:ebx
+ movzx ebx, word[VESAINFO+14]
+ mov ax, word[VESAINFO+16]
+ mov gs, ax
+
+ ; convert modes to own structure
+
+ xor esi, esi ; number of avail modes
+
+.mode_loop:
+ ; get mode info
+ mov cx, [gs:ebx] ; video mode into cx
+ cmp cx, 0xFFFF ; 0xFFFF is terminator, no suitable mode has been found
+ je .mode_done
+ mov ax, 0x4F01 ; get VESA mode information
+ mov di, VESAMODE ; vesa mode info struct buffer
+ int 0x10
+
+ cmp ax, 0x004F ; check ax for correct magic number
+ jne .fail_modeinfo
+
+ mov al, byte[VESAMODE] ; get attributes
+ and al, 0b10000000 ; extract bit 7, indicates linear framebuffer support
+ jz .mode_next
+
+ mov al, byte[VESAMODE+25] ; get bpp (bits per pixel)
+ cmp al, 32
+ jne .mode_next
+
+ push ebx ; print_dec and print_str modify ebx
+
+ mov eax, esi
+ mov ebx, 12
+ mul ebx
+ mov edi, eax
+ add edi, OWNMODE
+
+ mov [edi+10], cx ; copy mode
+
+ ; print selector
+ mov al, '['
+ call print_chr
+
+ mov eax, esi
+ add eax, 'a'
+ call print_chr
+
+ mov al, ']'
+ call print_chr
+
+ mov al, ' '
+ call print_chr
+
+ mov ax, [VESAMODE+16] ; copy pitch
+ mov [edi+0], ax
+
+ movzx eax, word[VESAMODE+18] ; copy width
+ mov [edi+2], ax
+ call print_dec
+
+ mov al, 'x'
+ call print_chr
+
+ movzx eax, word[VESAMODE+20] ; copy height
+ mov [edi+4], ax
+ call print_dec
+ call newline
+
+ mov eax, [VESAMODE+40] ; copy framebuffer
+ mov [edi+6], eax
+
+ pop ebx
+
+ inc esi
+ cmp esi, 'z'-'a' ; only print up to z
+ jg .mode_done
+
+.mode_next:
+ add ebx, 2 ; increase mode pointer
+ jmp .mode_loop ; loop
+
+.mode_done:
+ cmp esi, 0
+ je .fail_nomode
+
+.input:
+ mov ebx, .select_prompt
+ call print_str
+
+ mov ah, 0x00 ; get keypress, blocking
+ int 0x16
+
+ call print_chr ; echo user input
+
+ movzx edi, al ; backup al
+ call newline
+
+ sub edi, 'a'
+ cmp edi, esi
+ jb .valid ; check validity
+
+ mov ebx, .invalid
+ call print_str
+
+ jmp .input
+
+.valid:
+ ; convert selected number to address
+ mov eax, edi
+ mov ebx, 12
+ mul ebx
+ add eax, OWNMODE
+
+ ; copy to final gfx info location
+ mov ebx, [eax+0]
+ mov [GFXINFO+0], ebx
+
+ mov ebx, [eax+4]
+ mov [GFXINFO+4], ebx
+
+ mov bx, [eax+8]
+ mov [GFXINFO+8], bx
+
+ ;mov edi, eax
+ ;mov eax, [edi+6]
+ ;call print_hex
+ ;call newline
+ ;mov eax, edi
+ ;jmp $
+
+ ; set mode
+ mov bx, [eax+10] ; video mode in bx (first 13 bits)
+ or bx, 1 << 14 ; set bit 14: enable linear frame buffer
+ and bx, 0b0111111111111111 ; clear deprecated bit 15
+ mov ax, 0x4F02 ; set VBE mode
+ int 0x10
+
+ ret
+
+.msg: db "setting up vesa", 10, 13, 0
+.vbe2: db "VBE2"
+.vesa: db "VESA"
+.select_msg: db "avaliable video modes:", 10, 13, 0
+.select_prompt: db "select video mode: ", 0
+.invalid: db "invalid input", 10, 13, 0
+
+.fail_getinfo:
+ mov ebx, .fail_getinfo_msg
+ jmp .fail
+
+.fail_modeinfo:
+ mov ebx, .fail_modeinfo_msg
+ jmp .fail
+
+.fail_nomode:
+ mov ebx, .fail_nomode_msg
+ jmp .fail
+
+.fail_getinfo_msg: db "failed getting vesa bios info", 10, 13, 0
+.fail_modeinfo_msg: db "failed getting video mode info", 10, 13, 0
+.fail_nomode_msg: db "no suitable video modes available", 10, 13, 0
+
+.fail:
+ call print_str
+ jmp $
--- /dev/null
+%define COLOR_BLACK 0
+%define COLOR_BLUE 1
+%define COLOR_GREEN 2
+%define COLOR_CYAN 3
+%define COLOR_RED 4
+%define COLOR_MAGENTA 5
+%define COLOR_BROWN 6
+%define COLOR_LIGHT_GREY 7
+%define COLOR_DARK_GREY 8
+%define COLOR_LIGHT_BLUE 9
+%define COLOR_LIGHT_GREEN 10
+%define COLOR_LIGHT_CYAN 11
+%define COLOR_LIGHT_RED 12
+%define COLOR_LIGHT_MAGENTA 13
+%define COLOR_LIGHT_BROWN 14
+%define COLOR_WHITE 15
--- /dev/null
+%include "stage3/colors.asm"
+global print_chr, print_str, print_dec, print_hex, clear_screen, newline
+extern memcpy
+
+section .data
+
+pos:
+.row: db 0
+.col: db 0
+
+cursor: dq 0xB8000
+color: db COLOR_WHITE | (COLOR_BLACK << 4)
+
+section .text
+
+set_color:
+ shl sil, 4
+ add dil, sil
+ mov [color], dil
+
+update_cursor:
+ mov rbx, [cursor]
+ sub rbx, 0xB8000
+ shr rbx, 1
+
+ mov dx, 0x3D4
+ mov al, 14
+ out dx, al
+
+ mov dx, 0x3D5
+ mov al, bh
+ out dx, al
+
+ mov dx, 0x3D4
+ mov al, 15
+ out dx, al
+
+ mov dx, 0x3D5
+ mov al, bl
+ out dx, al
+
+ ret
+
+set_chr:
+ mov rax, [cursor]
+ mov byte[rax], dil
+ inc rax
+ mov dil, [color]
+ mov [rax], dil
+ inc rax
+ mov [cursor], rax
+ jmp update_cursor
+
+vertical_tab:
+ mov al, [pos.row]
+ inc al
+ cmp al, 25
+ je .scroll
+ mov [pos.row], al
+ mov rax, [cursor]
+ add rax, 160
+ mov [cursor], rax
+ jmp update_cursor
+.scroll:
+ mov rdi, 0xB8000
+ mov rsi, 0xB80A0
+ mov rdx, 0xF00
+ jmp memcpy
+
+carriage_return:
+ mov rax, [cursor]
+ xor rbx, rbx
+ mov bl, [pos.col]
+ shl bl, 1
+ sub rax, rbx
+ mov [cursor], rax
+ mov byte[pos.col], 0
+ jmp update_cursor
+
+newline:
+ call vertical_tab
+ jmp carriage_return
+
+print_chr:
+ cmp dil, 10
+ je newline
+ cmp dil, 11
+ je vertical_tab
+ cmp dil, 13
+ je carriage_return
+ mov al, [pos.col]
+ inc al
+ cmp al, 80
+ je .newline
+ mov [pos.col], al
+ jmp set_chr
+.newline:
+ push rdi
+ call newline
+ pop rdi
+ jmp set_chr
+
+print_str:
+ mov rax, rdi
+.print:
+ mov dil, [rax]
+ cmp dil, 0
+ je .return
+ push rax
+ call print_chr
+ pop rax
+ inc rax
+ jmp .print
+.return:
+ ret
+
+print_hex:
+ mov rsi, 0x10
+ jmp print_num
+print_dec:
+ mov rsi, 10
+print_num:
+ mov rax, rdi
+ xor rcx, rcx
+.convert:
+ inc rcx
+ xor rdx, rdx
+ div rsi
+ cmp dl, 10
+ jb .digit
+ add dl, 'A'-10
+ jmp .next
+.digit:
+ add dl, '0'
+.next:
+ push rdx
+ cmp rax, 0
+ jne .convert
+.print:
+ cmp rcx, 0
+ je .return
+ dec rcx
+ pop rdi
+ push rcx
+ call print_chr
+ pop rcx
+ jmp .print
+.return:
+ ret
+
+clear_screen:
+ mov qword[cursor], 0xB8000
+.clr:
+ cmp qword[cursor], 0xB8FA0
+ je .return
+ mov dil, ' '
+ call set_chr
+ jmp .clr
+.return:
+ mov qword[cursor], 0xB8000
+ mov byte[pos.row], 0
+ mov byte[pos.col], 0
+ jmp update_cursor
--- /dev/null
+global _start
+extern print_str, print_dec, print_chr, clear_screen, paging
+
+section .data
+
+headline: db "nyax stage3", 10, 10, 0
+
+disclaimer: db \
+ "NyaX", 10, \
+ "(C) 2022 Flecken-chan", 10, \
+ "Dis progwam comes with ABSOLUTELY NO WAWWANTY", 10, \
+ "Dis iz fwee software, and your'e welcome to redistwibute it", 10, " under certain conditions", 10, 0
+
+section .text
+
+_start:
+ call clear_screen
+
+ call paging
+
+ mov rdi, headline
+ call print_str
+
+ mov rdi, disclaimer
+ call print_str
+
+ xor rdi, rdi
+.loop:
+ push rdi
+ mov dil, 13
+ call print_chr
+ mov rdi, [rsp]
+ call print_dec
+ pop rdi
+ inc rdi
+ jmp .loop
--- /dev/null
+global memcpy, memmove
+
+section .text
+
+memcpy:
+.bulk_copy:
+ cmp rdx, 8
+ jl .bytewise_copy
+ mov rax, qword[rsi]
+ mov qword[rdi], rax
+ sub rdx, 8
+ add rdi, 8
+ add rsi, 8
+.bytewise_copy:
+ cmp rdx, 0
+ je .return
+ mov al, byte[rsi]
+ mov byte[rdi], al
+ dec rdx
+ inc rdi
+ inc rsi
+ jmp .bytewise_copy
+.return:
+ ret
+
+memmove:
+ mov rcx, rdx
+.bulk_read:
+ cmp rdx, 8
+ jl .bytewise_read
+ push qword[rsi]
+ add rsi, 8
+ sub rdx, 8
+ jmp .bulk_read
+.bytewise_read:
+ cmp rdx, 0
+ je .bulk_write
+ dec rsp
+ mov al, byte[rsi]
+ mov byte[rsp], al
+ inc rsi
+ dec rdx
+ jmp .bytewise_read
+.bulk_write:
+ cmp rcx, 8
+ jl .bytewise_write
+ pop qword[rdi]
+ add rdi, 8
+ sub rcx, 8
+.bytewise_write:
+ cmp rcx, 0
+ je .return
+ mov al, byte[rsp]
+ mov byte[rdi], al
+ inc rsp
+ inc rdi
+ dec rcx
+.return:
+ ret
--- /dev/null
+global paging
+extern print_hex, print_chr, newline, print_dec, print_str
+global paging
+
+section .data
+
+pagebuf:
+ .ptr: dq 0x5000
+ .size: dq 0x3000
+ .used: dq 0
+
+section .text
+alloc:
+ mov rdi, .msg
+ call print_str
+ jmp $
+.msg: db "cock", 10, 0
+
+tables:
+; level 4
+ mov rax, 0xfff
+ not rax ; offset mask
+
+ mov rbx, -1 ; low bits mask
+ shl rbx, 3 ;
+
+ xor rcx, rcx
+
+ mov r14, r10
+ mov r13, r10
+ mov r12, r10
+ mov r11, r10
+
+ not rcx ; negate remainder mask
+ and r14, rcx ; apply remainder mask
+ mov rcx, -1 ; reset remainder mask
+ shl rcx, 12+9+9+9 ; update remainder mask
+
+ shr r14, 12+9+9+9-3 ; divide
+ and r14, rbx ; clear lower bits
+
+ mov rdx, 0x1000 ; offset
+ and rdx, rax ; offset mask
+ add r14, rdx ; add offset
+
+ not rcx ; negate remainder mask
+ and r13, rcx ; apply remainder mask
+ mov rcx, -1 ; reset remainder mask
+ shl rcx, 12+9+9 ; update remainder mask
+
+ shr r13, 12+9+9-3 ; divide
+ and r13, rbx ; clear lower bits
+
+ mov rdx, [r14] ; offset
+ jnz .exist3
+ call alloc
+.exist3:
+ and rdx, rax ; offset mask
+ add r13, rdx ; add offset
+
+
+ not rcx ; negate remainder mask
+ and r12, rcx ; apply remainder mask
+ mov rcx, -1 ; reset remainder mask
+ shl rcx, 12+9 ; update remainder mask
+
+ shr r12, 12+9-3 ; divide
+ and r12, rbx ; clear lower bits
+
+ mov rdx, [r13] ; offset
+ jnz .exist2
+ call alloc
+.exist2:
+ and rdx, rax ; offset mask
+ add r12, rdx ; add offset
+
+
+ not rcx ; negate remainder mask
+ and r11, rcx ; apply remainder mask
+
+ mov rcx, -1 ; reset remainder mask
+ shl rcx, 12 ; update remainder mask
+
+ shr r11, 12-3 ; divide
+ and r11, rbx ; clear lower bits
+
+ mov rdx, [r12] ; offset
+ jnz .exist1
+ call alloc
+.exist1:
+ and rdx, rax ; offset mask
+ add r11, rdx ; add offset
+
+ ret
+
+; level1
+ mov rax, r11
+ xor rdx, rdx
+ mov rbx, 8
+ mul rbx
+ mov r11, rax
+ add r11, [r12]
+ sub r11, 3
+
+ ret
+
+space:
+ mov dil, ' '
+ jmp print_chr
+
+paging:
+ mov r8, 0x0500 ; start of extended memory map
+ movzx r9, word[0x1000-10-2] ; number of map entries
+
+ mov r15, pagebuf
+
+.loop:
+ ;mov r10, [r8]
+ ;call tables
+
+ mov r10, 0xfffff
+ call tables
+
+ mov rdi, r14
+ call print_hex
+ call space
+
+ mov rdi, r13
+ call print_hex
+ call space
+
+ mov rdi, r12
+ call print_hex
+ call space
+
+ mov rdi, r11
+ call print_hex
+ call space
+
+ mov rdi, [r11]
+ call print_hex
+
+ jmp $
+
+ mov rdi, r12
+ call print_hex
+ call space
+
+ mov rdi, r11
+ call print_hex
+ call space
+
+ mov rdi, r10
+ call print_hex
+ call space
+
+
+
+ call newline
+
+ jmp $
+
+ ;jmp $
+
+ ;mov rcx, 1 << 63
+ ;or rdi, rcx
+ ;call print_hex
+
+ ;mov dil, ' '
+ ;call print_chr
+
+ ;mov rax, [rsp]
+ ;mov rdi, [rax+8]
+
+ ;mov rcx, 1 << 63
+ ;or rdi, rcx
+ ;call print_hex
+
+ ;mov dil, ' '
+ ;call print_chr
+
+ ; mov rax, [rsp]
+ ;xor rdi, rdi
+ ;mov edi, [rax+16]
+ ;call print_dec
+
+ ;call newline
+
+ ;pop rax
+ add r8, 24
+
+ ;pop rbx
+
+ dec r9
+ jnz .loop
+
+ jmp $
+
+ ret