From 1e46a0f6b25bc6fdc6042d13fcf691c85fe235be Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 19 Dec 2020 21:09:05 -0800 Subject: 7356 --- apps/bos/4.asm | 124 +++++++++++++++++++++++++++++++++++++++---- apps/bos/gdt.asm | 46 ---------------- apps/bos/print_string.asm | 11 ---- apps/bos/print_string_pm.asm | 21 -------- apps/bos/switch_to_pm.asm | 34 ------------ 5 files changed, 115 insertions(+), 121 deletions(-) delete mode 100644 apps/bos/gdt.asm delete mode 100644 apps/bos/print_string.asm delete mode 100644 apps/bos/print_string_pm.asm delete mode 100644 apps/bos/switch_to_pm.asm diff --git a/apps/bos/4.asm b/apps/bos/4.asm index ae079446..067ae95f 100644 --- a/apps/bos/4.asm +++ b/apps/bos/4.asm @@ -5,11 +5,6 @@ ; qemu-system-i386 boot.bin ; Or: ; bochs # bochsrc loads boot.bin -# -# Expected output inside emulator: -# Started in 16-bit Real Mode -# Successfully landed in 32-bit Protected Mode -# Look for the second line at the top of the emulated screen. ; A boot sector that enters 32-bit protected mode. [org 0x7c00] @@ -24,10 +19,121 @@ jmp $ -%include "print_string.asm" -%include "gdt.asm" -%include "print_string_pm.asm" -%include "switch_to_pm.asm" +print_string: + pusha + mov ah, 0x0e +loop: + mov al, [bx] + int 0x10 + add bx, 1 + cmp al, 0 + jne loop + popa + ret + +; GDT +gdt_start: + +gdt_null: ; the mandatory null descriptor + dd 0x0 ; ’dd’ means define double word (i.e. 4 bytes) + dd 0x0 + +gdt_code: ; the code segment descriptor + ; base=0x0, limit=0xfffff, + ; 1st flags: (present)1 (privilege)00 (descriptor type)1 -> 1001b + ; type flags: (code)1 (conforming)0 (readable)1 (accessed )0 -> 1010b + ; 2nd flags: (granularity)1 (32-bit default)1 (64-bit seg)0 (AVL)0 -> 1100b + dw 0xffff ; Limit (bits 0-15) + dw 0x0 ; Base (bits 0-15) + db 0x0 ; Base (bits 16 -23) + db 10011010b ; 1st flags, type flags + db 11001111b ; 2nd flags, Limit (bits 16-19) + db 0x0 ; Base (bits 24 -31) + +gdt_data: ;the data segment descriptor + ; Same as code segment except for the type flags: + ; type flags: (code)0 (expand down)0 (writable)1 (accessed)0 -> 0010b + dw 0xffff ; Limit (bits 0-15) + dw 0x0 ; Base (bits 0-15) + db 0x0 ; Base (bits 16 -23) + db 10010010b ; 1st flags, type flags + db 11001111b ; 2nd flags, Limit (bits 16-19) + db 0x0 ; Base (bits 24 -31) + +gdt_end: ; The reason for putting a label at the end of the + ; GDT is so we can have the assembler calculate + ; the size of the GDT for the GDT decriptor (below) + +; GDT descriptor +gdt_descriptor: + dw gdt_end - gdt_start - 1 ; Size of our GDT, always less one + ; of the true size + dd gdt_start ; Start address of our GDT + +; Define some handy constants for the GDT segment descriptor offsets, which +; are what segment registers must contain when in protected mode. For example, +; when we set DS = 0x10 in PM , the CPU knows that we mean it to use the +; segment described at offset 0x10 (i.e. 16 bytes) in our GDT, which in our +; case is the DATA segment (0x0 -> NULL; 0x08 -> CODE; 0x10 -> DATA) +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start + +[bits 32] +; Define some constants +VIDEO_MEMORY equ 0xb8000 +WHITE_ON_BLACK equ 0x0f +; prints a null -terminated string pointed to by EDX +print_string_pm: + pusha + mov edx, VIDEO_MEMORY ; Set edx to the start of vid mem. +print_string_pm_loop: + mov al, [ebx] ; Store the char at EBX in AL + mov ah, WHITE_ON_BLACK ; Store the attributes in AH + cmp al, 0 ; if (al == 0), at end of string , so + je print_string_pm_done + mov [edx], ax ; Store char and attributes at current + ; character cell. + add ebx , 1 ; Increment EBX to the next char in string. + add edx , 2 ; Move to next character cell in vid mem. + jmp print_string_pm_loop ; loop around to print the next char. +print_string_pm_done: + popa + ret ; Return from the function + +[bits 16] +; Switch to protected mode +switch_to_pm: + cli ; We must switch of interrupts until we have + ; set up the protected mode interrupt vector + ; otherwise interrupts will run riot. + + lgdt [gdt_descriptor] ; Load our global descriptor table, which defines + ; the protected mode segments (e.g. for code and data) + + mov eax, cr0 ; To make the switch to protected mode, we set + or eax, 0x1 ; the first bit of CR0, a control register + mov cr0, eax + + jmp CODE_SEG:init_pm ; Make a far jump (i.e. to a new segment) to our 32-bit + ; code. This also forces the CPU to flush its cache of + ; prefetched and real-mode decoded instructions, which can + ; cause problems. + +[bits 32] +; Initialise registers and the stack once in PM. +init_pm: + + mov ax, DATA_SEG ; Now in PM, our old segments are meaningless, + mov ds, ax ; so we point our segment registers to the + mov ss, ax ; data selector we defined in our GDT + mov es, ax + mov fs, ax + mov gs, ax + + mov ebp, 0x90000 ; Update our stack position so it is right + mov esp, ebp ; at the top of the free space. + + call BEGIN_PM ; Finally, call some well-known label [bits 32] ; This is where we arrive after switching to and initialising protected mode. diff --git a/apps/bos/gdt.asm b/apps/bos/gdt.asm deleted file mode 100644 index d9703551..00000000 --- a/apps/bos/gdt.asm +++ /dev/null @@ -1,46 +0,0 @@ -; GDT -gdt_start: - -gdt_null: ; the mandatory null descriptor - dd 0x0 ; ’dd’ means define double word (i.e. 4 bytes) - dd 0x0 - -gdt_code: ; the code segment descriptor - ; base=0x0, limit=0xfffff, - ; 1st flags: (present)1 (privilege)00 (descriptor type)1 -> 1001b - ; type flags: (code)1 (conforming)0 (readable)1 (accessed )0 -> 1010b - ; 2nd flags: (granularity)1 (32-bit default)1 (64-bit seg)0 (AVL)0 -> 1100b - dw 0xffff ; Limit (bits 0-15) - dw 0x0 ; Base (bits 0-15) - db 0x0 ; Base (bits 16 -23) - db 10011010b ; 1st flags, type flags - db 11001111b ; 2nd flags, Limit (bits 16-19) - db 0x0 ; Base (bits 24 -31) - -gdt_data: ;the data segment descriptor - ; Same as code segment except for the type flags: - ; type flags: (code)0 (expand down)0 (writable)1 (accessed)0 -> 0010b - dw 0xffff ; Limit (bits 0-15) - dw 0x0 ; Base (bits 0-15) - db 0x0 ; Base (bits 16 -23) - db 10010010b ; 1st flags, type flags - db 11001111b ; 2nd flags, Limit (bits 16-19) - db 0x0 ; Base (bits 24 -31) - -gdt_end: ; The reason for putting a label at the end of the - ; GDT is so we can have the assembler calculate - ; the size of the GDT for the GDT decriptor (below) - -; GDT descriptor -gdt_descriptor: - dw gdt_end - gdt_start - 1 ; Size of our GDT, always less one - ; of the true size - dd gdt_start ; Start address of our GDT - -; Define some handy constants for the GDT segment descriptor offsets, which -; are what segment registers must contain when in protected mode. For example, -; when we set DS = 0x10 in PM , the CPU knows that we mean it to use the -; segment described at offset 0x10 (i.e. 16 bytes) in our GDT, which in our -; case is the DATA segment (0x0 -> NULL; 0x08 -> CODE; 0x10 -> DATA) -CODE_SEG equ gdt_code - gdt_start -DATA_SEG equ gdt_data - gdt_start diff --git a/apps/bos/print_string.asm b/apps/bos/print_string.asm deleted file mode 100644 index 555e4d52..00000000 --- a/apps/bos/print_string.asm +++ /dev/null @@ -1,11 +0,0 @@ -print_string: - pusha - mov ah, 0x0e -loop: - mov al, [bx] - int 0x10 - add bx, 1 - cmp al, 0 - jne loop - popa - ret diff --git a/apps/bos/print_string_pm.asm b/apps/bos/print_string_pm.asm deleted file mode 100644 index 78904671..00000000 --- a/apps/bos/print_string_pm.asm +++ /dev/null @@ -1,21 +0,0 @@ -[bits 32] -; Define some constants -VIDEO_MEMORY equ 0xb8000 -WHITE_ON_BLACK equ 0x0f -; prints a null -terminated string pointed to by EDX -print_string_pm: - pusha - mov edx, VIDEO_MEMORY ; Set edx to the start of vid mem. -print_string_pm_loop: - mov al, [ebx] ; Store the char at EBX in AL - mov ah, WHITE_ON_BLACK ; Store the attributes in AH - cmp al, 0 ; if (al == 0), at end of string , so - je print_string_pm_done - mov [edx], ax ; Store char and attributes at current - ; character cell. - add ebx , 1 ; Increment EBX to the next char in string. - add edx , 2 ; Move to next character cell in vid mem. - jmp print_string_pm_loop ; loop around to print the next char. -print_string_pm_done: - popa - ret ; Return from the function diff --git a/apps/bos/switch_to_pm.asm b/apps/bos/switch_to_pm.asm deleted file mode 100644 index aeef97c0..00000000 --- a/apps/bos/switch_to_pm.asm +++ /dev/null @@ -1,34 +0,0 @@ -[bits 16] -; Switch to protected mode -switch_to_pm: - cli ; We must switch of interrupts until we have - ; set up the protected mode interrupt vector - ; otherwise interrupts will run riot. - - lgdt [gdt_descriptor] ; Load our global descriptor table, which defines - ; the protected mode segments (e.g. for code and data) - - mov eax, cr0 ; To make the switch to protected mode, we set - or eax, 0x1 ; the first bit of CR0, a control register - mov cr0, eax - - jmp CODE_SEG:init_pm ; Make a far jump (i.e. to a new segment) to our 32-bit - ; code. This also forces the CPU to flush its cache of - ; prefetched and real-mode decoded instructions, which can - ; cause problems. - -[bits 32] -; Initialise registers and the stack once in PM. -init_pm: - - mov ax, DATA_SEG ; Now in PM, our old segments are meaningless, - mov ds, ax ; so we point our segment registers to the - mov ss, ax ; data selector we defined in our GDT - mov es, ax - mov fs, ax - mov gs, ax - - mov ebp, 0x90000 ; Update our stack position so it is right - mov esp, ebp ; at the top of the free space. - - call BEGIN_PM ; Finally, call some well-known label -- cgit 1.4.1-2-gfad0