Re: Debugging the OS with VirtualBox
Posted: Mon Mar 22, 2021 6:31 pm
Wouldn't it be a better idea to learn the x86 architecture before trying to write an OS for it?So I'm a bit retarded when I need to code in assembly...
The Place to Start for Operating System Developers
http://f.osdev.org/
Wouldn't it be a better idea to learn the x86 architecture before trying to write an OS for it?So I'm a bit retarded when I need to code in assembly...
Code: Select all
%define LIN_TO_FAR_ADDR(linaddr) (((linaddr >> 4) << 16) | (linaddr & 0xf))
mov ebx, dword LIN_TO_FAR_ADDR(0x00007E00)
[...]
;inside a loop
; increase address
xor eax, eax
mov ax, word [bpb_SectorsPerCluster]
mul word [bpb_BytesPerSector]
mov ecx, eax
shr eax, 4
shl eax, 16
and ecx, 0xF
or eax, ecx
add ebx, eax
; check if riporto
mov eax, ebx
and eax, (1 << 4)
cmp eax, 0
je .nextCluster
; fix riporto
xor ebx, 1 << 4
add ebx, 1 << 16
jmp .nextCluster
Theoretically, I learned it and I can code using it but I still can only do very simple tasks. I know the syntax, I get the logic, the only thing that I miss is experience and I hope to retrieve it by tinkering with this bootloader.Gigasoft wrote:Wouldn't it be a better idea to learn the x86 architecture before trying to write an OS for it?So I'm a bit retarded when I need to code in assembly...
Sectors are always a multiple of 16 bytes large, so you never need to modify the offset part of the address, just the segment part. You can remove all of the code to adjust the offset part.Bonfra wrote:basically what it does is adding to ebx (which contains a far address) a a certain bias calculated in the first lines. I wasn't sure about how to increase a non linear addresso so I went for this approach; it works but it's a bit clunky, do you know a better way?
Well, It works with QEMU...sj95126 wrote:Well, if I'm reading the VirtualBox output right, you're going into 64-bit mode with an invalid GDT.
Code: Select all
Mem.GDT equ 0x00004500
.loadGDT64:
; Copy the GDT to its memory layout location.
mov si, GDT64.Table
mov di, Mem.GDT
mov cx, GDT64.Table.Size
shr cx, 1
rep movsw
lgdt [GDT64.Table.Pointer]
Code: Select all
00:00:10.288550 Guest GDT (GCAddr=0000000000004500 limit=27):
00:00:10.288553 0008 - 00000000 00009300 - base=00000000 limit=00000000 dpl=0 DataRW Accessed Present 16-bit
00:00:10.288555 0010 - 00000000 00209b00 - base=00000000 limit=00000000 dpl=0 CodeER Accessed Present 16-bit
00:00:10.288556 0018 - 00000000 0000f200 - base=00000000 limit=00000000 dpl=3 DataRW Present 16-bit
00:00:10.288557 0020 - 00000000 0020fa00 - base=00000000 limit=00000000 dpl=3 CodeER Present 16-bit
According to your log file, it's getting a bit further than that before it triple faults.Bonfra wrote:Whenever I enable paging and protected mode updating the content of CR0, VirtualBox throws what it calls "a critical error"... I've tried to locate something useful in the log file but I couldn't find anything so I'm posing it here.
Code: Select all
00:00:10.286852 rip=000000000010c44f
Code: Select all
00:00:10.286856 cr0=0000000080000013
Code: Select all
00:00:10.286905 EFER =0000000000000500
Code: Select all
00:00:10.286953 CPUM0: 0010:000000000010c44f 88 10 mov byte [rax], dl
Code: Select all
00:00:10.286848 rax=000000000052c000
I think it's just displaying them wrong. It shows the appropriate bits are set to put the CPU in 64-bit mode.sj95126 wrote:This pattern (data cpl0, code cpl0, data cpl3, code cpl3) matches your 64-bit GDT but apparently it thinks you've set 16-bit segments.
I've located the point where it triple faults with infinite jumps to the line where it enables PG and PE. (this line) maybe has to do with the way I set up paging?Octocontrabass wrote: According to your log file, it's getting a bit further than that before it triple faults.
That's odd... I've tried to stick an infinite loop at the start of the kernel code but it never triggers so it can't get to that address unless some weird jump happens.Octocontrabass wrote: That address (0x10c44f) should be somewhere inside your kernel binary.
I've tried to attach a copy of the binary but it's too big so here is a direct link to download it, and here is the code if you want to check something particular. It links to other two libs but them are also present in that repoOctocontrabass wrote: I'm not sure exactly where because I don't have a copy of your kernel binary.
Did you use an infinite near JMP? The instruction immediately following a MOV to CR0 that sets PE needs to be a far JMP. A near JMP could cause a fault.Bonfra wrote:I've located the point where it triple faults with infinite jumps to the line where it enables PG and PE. (this line)
Bonfra wrote:That's odd... I've tried to stick an infinite loop at the start of the kernel code but it never triggers so it can't get to that address unless some weird jump happens.
Code: Select all
kernel.sys: file format elf64-x86-64
kernel.sys
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0000000000101008
Code: Select all
jmp Mem.Kernel.Code + (load - 0x7E00) ; wierd elf bug
Code: Select all
Mem.Kernel.Code equ 0x00101000
Yes, the instruction right after the MOV to CR0 is a far jump to the 64 bit part and at the start of this I've added an infinite near jump, it crushes before reaching that jump. If I place the infinite jump before the mov it does not crush.Octocontrabass wrote: Did you use an infinite near JMP? The instruction immediately following a MOV to CR0 that sets PE needs to be a far JMP. A near JMP could cause a fault.
I somewhere read that the elf header is always 0x100 bytes and that the entry point is always located after it. Obviously, I must have misunderstood.Octocontrabass wrote: You're not jumping to the entry point, I'd say that's a pretty weird jump.
Ups, fixed. Well it does not change the result but still is good to be fixed, thanks.Octocontrabass wrote: Perhaps you meant to put this variable in the .bss section? Either that, or you need to parse the headers to find the entry point.
Does the log say it crashes in the same place as before? If it does, you might have better luck stepping through the code to see where it gets lost.Bonfra wrote:Yes, the instruction right after the MOV to CR0 is a far jump to the 64 bit part and at the start of this I've added an infinite near jump, it crushes before reaching that jump. If I place the infinite jump before the mov it does not crush.
The entry point is wherever you put it. If you want it to be at offset 0x1000 in the ELF file, you have to put it there.Bonfra wrote:I somewhere read that the elf header is always 0x100 bytes and that the entry point is always located after it. Obviously, I must have misunderstood.
I've double-checked and it turns out it crashes in the exact address I set the jump. So if I place the jump right at the start of the kernel it triple faults at 0x101000 (which is the address of the entry point)Octocontrabass wrote: Does the log say it crashes in the same place as before? If it does, you might have better luck stepping through the code to see where it gets lost.
Code: Select all
00:00:10.286859 gdtr=0000000000004500:0027 idtr=0000000000000000:ffff eflags=00210206