boot.asm:
[org 0x7c00]
[BITS 16]
boot:
mov bp, 0x9000 ; set the stack
mov sp, bp
mov bx, MSG_REAL_MODE
call print_string
call switch_to_pm
jmp $
%include "print/print.asm"
%include "gdt.asm"
%include "print_32.asm"
%include "switch_to_pm.asm"
[BITS 32]
; We're in 32-bit Protected Mode
BEGIN_PM:
mov ebx, MSG_PROT_MODE
call print_string_pm
jmp $
MSG_REAL_MODE:
db "Started in 16-bit Real Mode", 0
MSG_PROT_MODE:
db "Sucessfully landed in 32-bit Protected Mode", 0
; Bootsector padding
times 510-($-$$) db 0
dw 0xAA55
gdt.asm:
[BITS 16]
align 4
gdtr:
dw gdt_end-gdt_start-1
dd gdt_start
; GDT
gdt_start:
dd 0x0 ; 'dd' means define double word (4 bytes)
dd 0x0
gdt_code: ; the code segment descriptor
; base=0x0, limit=0 xfffff,
; 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 0x9A ; 1st flags, type flags
db 11001111b ; 2nd flags, linit (bits 16-19)
db 0x0 ; base (bits 24-31)
gdt_data: ; the data segment descriptor
; same as code segment execpt 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 0x92 ; 1st flags, type flags
db 11001111b ; 2nd flags, linit (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 assembly calculate
; the size of the GDT for the GDT descriptor (below)
; GDT descriptor
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; size of the GDT, always less one
; of the true size
dd gdt_start ; start address of the GDT
; define some handy constants for the GDT segment descriptor offsets, which
; are what segment registers must contain when in protected mode
; (0x0 = NULL; 0x08 = CODE; 0x10 = DATA)
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
print_32.asm:
[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 ah, WHITE_ON_BLACK ; Set edx to the start of video memory
print_string_pm_loop:
mov al, [ebx] ; store the char at ebx in al
mov al, WHITE_ON_BLACK ; store the attributes in ah
cmp al, 0 ; if (al == 0), at end of string, so
je print_string_pm_done; jump to 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 the string
add edx, 2 ; move to next character cell in video memory
jmp print_string_pm_loop
print_string_pm_done:
popa
ret ; return from the function
The only reason I know of that would cause QEMU to just restart in a loop is a triple fault, but I have no idea where that's coming from.
I've tried logging the QEMU interrupts with -d int
but I have no idea what it means whatsoever. Here's the output log file:
SMM: enter
EAX=00000001 EBX=0000000b ECX=02000000 EDX=02000628
ESI=00000000 EDI=02000000 EBP=07fa84c0 ESP=00006c80
EIP=000ebad0 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00cf9b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 000f6070 00000037
IDT= 000f60ae 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00007113 CCD=00000001 CCO=LOGICB
EFER=0000000000000000
SMM: after RSM
EAX=00000001 EBX=0000000b ECX=02000000 EDX=02000628
ESI=00000000 EDI=02000000 EBP=07fa84c0 ESP=00006c80
EIP=000ebad0 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 000f6070 00000037
IDT= 000f60ae 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=000f7cd9 ECX=00001234 EDX=0000db80
ESI=07fbdb3b EDI=00006c40 EBP=00006c00 ESP=00006c00
EIP=00007cd8 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =db80 000db800 ffffffff 008f9300
CS =f000 000f0000 ffffffff 008f9b00
SS =0000 00000000 ffffffff 008f9300
DS =0000 00000000 ffffffff 008f9300
FS =0000 00000000 ffffffff 008f9300
GS =0000 00000000 ffffffff 008f9300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 00000000 00000000
IDT= 00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000004 CCD=00006c00 CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=000f7cd9 ECX=00001234 EDX=0000db80
ESI=07fbdb3b EDI=00006c40 EBP=00006c00 ESP=00006c00
EIP=000f7cd9 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 000f6070 00000037
IDT= 000f60ae 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=00007cf3 ECX=00005678 EDX=000eac40
ESI=07fbdb3b EDI=000eac40 EBP=00006c00 ESP=00006c00
EIP=000f7cf2 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 000f6070 00000037
IDT= 000f60ae 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00006bec CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=00007cf3 ECX=00005678 EDX=000eac40
ESI=07fbdb3b EDI=000eac40 EBP=00006c00 ESP=00006c00
EIP=00007cf3 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =db80 000db800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =0000 00000000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 00000000 00000000
IDT= 00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000004 CCD=00000001 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=000f7cd9 ECX=00001234 EDX=0000db80
ESI=07fbdb3b EDI=0000692e EBP=000068ee ESP=000068ee
EIP=00007cd8 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =db80 000db800 ffffffff 008f9300
CS =f000 000f0000 ffffffff 008f9b00
SS =0000 00000000 ffffffff 008f9300
DS =0000 00000000 ffffffff 008f9300
FS =0000 00000000 ffffffff 008f9300
GS =ca00 000ca000 ffffffff 008f9300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 00000000 00000000
IDT= 00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000004 CCD=000068ee CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=000f7cd9 ECX=00001234 EDX=0000db80
ESI=07fbdb3b EDI=0000692e EBP=000068ee ESP=000068ee
EIP=000f7cd9 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 000f6070 00000037
IDT= 000f60ae 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=00000000 CCO=EFLAGS
EFER=0000000000000000
SMM: enter
EAX=000000b5 EBX=00007cf3 ECX=00005678 EDX=00000005
ESI=07fbdb3b EDI=00000000 EBP=000068ee ESP=000068ee
EIP=000f7cf2 EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT= 000f6070 00000037
IDT= 000f60ae 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000000 CCD=000068da CCO=EFLAGS
EFER=0000000000000000
SMM: after RSM
EAX=000000b5 EBX=00007cf3 ECX=00005678 EDX=00000005
ESI=07fbdb3b EDI=00000000 EBP=000068ee ESP=000068ee
EIP=00007cf3 EFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =db80 000db800 ffffffff 00809300
CS =f000 000f0000 ffffffff 00809b00
SS =0000 00000000 ffffffff 00809300
DS =0000 00000000 ffffffff 00809300
FS =0000 00000000 ffffffff 00809300
GS =ca00 000ca000 ffffffff 00809300
LDT=0000 00000000 0000ffff 00008200
TR =0000 00000000 0000ffff 00008b00
GDT= 00000000 00000000
IDT= 00000000 000003ff
CR0=00000010 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=00000004 CCD=00000001 CCO=EFLAGS
EFER=0000000000000000
No idea what's wrong. The log file just repeats that block of text over and over (which makes sense, as it was restarting in a loop)
CodePudding user response:
The print_string_pm has multiple issues!
mov ah, WHITE_ON_BLACK ; Set edx to the start of video memory
The code does not setup the video output address in EDX
. Depending on the pre-existing value in EDX
, you might be destroying something important!
mov al, WHITE_ON_BLACK ; store the attributes in ah cmp al, 0 ; if (al == 0), at end of string, so je print_string_pm_done
To make matters worse, these lines will make the loop never end (WHITE_ON_BLACK is non-zero). So the above mentioned destroying is guaranteed to happen (I believe).
Try next code:
VIDEO_MEMORY equ 0xB8000
WHITE_ON_BLACK equ 0x0F
; prints a null-terminated string pointed to by EBX
print_string_pm:
pusha
mov edx, VIDEO_MEMORY
mov ah, WHITE_ON_BLACK
print_string_pm_loop:
mov al, [ebx]
cmp al, 0
je print_string_pm_done
mov [edx], ax
add ebx, 1
add edx, 2
jmp print_string_pm_loop
print_string_pm_done:
popa
ret
CodePudding user response:
I've just fixed it. After applying the fix @SepRoland gave me in his answer, I realized on line 17 of switch_to_pm.asm, I put init_pm
instead of CODE_SEG:init_pm
, so instead of preforming a far jump, I accidentally preformed a short jump. My code now works, thanks everyone.