Page 1 of 2
Triple fault upon call to extern function
Posted: Sat Apr 10, 2010 7:10 am
by Benjamin1996
Hello everyone!
My problem is that when I try to execute an extern function call from my bootloader, my CPU triple faults and resets.
This is my 32 bit "protectedMode" function, located in bootloader.asm:
Code: Select all
[bits 32]
[extern kernel]
protectedMode:
mov ax, 0x0010
mov ds, ax ;Point ds to the code descriptor
mov ss, ax ;Point ss to the code descriptor
mov esp, 0x90000 ;Set the stack base to 0x90000
call kernel
And this is kernel.asm:
Code: Select all
[bits 32]
[global kernel]
kernel:
mov edi, 0xb8000 ;Point edi to the color video memory
mov byte [edi + 800], 'K'
mov byte [edi + 801], 0x0004 ;Display a red 'K' on a black background.
jmp $ ;Hang the stub-kernel.
And this is my build.bat file:
Code: Select all
@echo off
nasm -f elf bootloader.asm -o bootloader.elf
nasm -f elf kernel.asm -o kernel.elf
ld -e kernel -o kernel.o kernel.elf
ld -Ttext 0x7c00 -o os.o bootloader.elf kernel.elf
objcopy -R .note -R .comment -S -O binary os.o os.bin
echo os.bin created!
rawwrite.exe
For testing, I'm using Bochs on Windows, and this is the message printed in bochsout.txt upon triple fault:
Code: Select all
00025746133i[CPU0 ] 0x000000000000fda8>> int1 : F1
00025746133e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
I would love some help
.
Best regards,
-Benjamin.
Re: Triple fault upon call to extern function
Posted: Sat Apr 10, 2010 8:53 am
by qw
You are using a code descriptor for the stack?
Re: Triple fault upon call to extern function
Posted: Sat Apr 10, 2010 1:43 pm
by Gigasoft
According to the error message, the call instruction isn't the problem. Are you sure that everything is loaded at the right address? Use the X command in bochs to examine various addresses and check that they correspond to the data in os.bin. And check that the addresses used in the code are right.
Re: Triple fault upon call to extern function
Posted: Sat Apr 10, 2010 2:40 pm
by Benjamin1996
Gigasoft wrote:According to the error message, the call instruction isn't the problem. Are you sure that everything is loaded at the right address? Use the X command in bochs to examine various addresses and check that they correspond to the data in os.bin. And check that the addresses used in the code are right.
To be completely honest, I've never used Bochs debugger before, so could you please show me how to use the 'x' command properly?
Re: Triple fault upon call to extern function
Posted: Sat Apr 10, 2010 4:11 pm
by Gigasoft
X examines a linear address, and XP a physical one. For example, to display 32 dwords starting at 0x7e00 physical, you'd write xp /32 0x7e00. To display 20 ASCII characters at 0x7e00, write xp /20cb 0x7e00. If you don't use byte format for characters, the characters will be reversed.
It's much easier to read the output if you enlarge the console before issuing the command. You can get more information on a command by typing "help" followed by the name of the command.
Re: Triple fault upon call to extern function
Posted: Sun Apr 11, 2010 2:32 am
by Benjamin1996
Gigasoft wrote:X examines a linear address, and XP a physical one. For example, to display 32 dwords starting at 0x7e00 physical, you'd write xp /32 0x7e00. To display 20 ASCII characters at 0x7e00, write xp /20cb 0x7e00. If you don't use byte format for characters, the characters will be reversed.
It's much easier to read the output if you enlarge the console before issuing the command. You can get more information on a command by typing "help" followed by the name of the command.
Alright thanks. Well, to me it seems like everything is okay in terms of memory locations.
Do you think there's a possibility that I don't have A20 enabled correctly, and therefore haven't got access to more than 1MB of memory?
Re: Triple fault upon call to extern function
Posted: Mon Apr 12, 2010 9:53 am
by Darwish
Hi,
Benjamin1996 wrote:
This is my 32 bit "protectedMode" function, located in bootloader.asm:
Code: Select all
[bits 32]
[extern kernel]
protectedMode:
mov ax, 0x0010
mov ds, ax ;Point ds to the code descriptor
mov ss, ax ;Point ss to the code descriptor
mov esp, 0x90000 ;Set the stack base to 0x90000
call kernel
The regular x86 'call' instruction takes an
%IP-relative address. If your code above is run from a different %IP than the one it's originally linked to, the relative address calculation becomes invalid.
I've faced such a situation while writing my kernel head, which was physical-addresses linked, but the portion of it calling the C entry point was run using a virtualized (different) %ip. A solution was getting rid of %IP-relativeness all together and use a near absolute indirect jump (opcode = FF):
Hope that helps ..
Re: Triple fault upon call to extern function
Posted: Mon Apr 12, 2010 1:23 pm
by Benjamin1996
Darwish wrote:Hi,
Benjamin1996 wrote:
This is my 32 bit "protectedMode" function, located in bootloader.asm:
Code: Select all
[bits 32]
[extern kernel]
protectedMode:
mov ax, 0x0010
mov ds, ax ;Point ds to the code descriptor
mov ss, ax ;Point ss to the code descriptor
mov esp, 0x90000 ;Set the stack base to 0x90000
call kernel
The regular x86 'call' instruction takes an
%IP-relative address. If your code above is run from a different %IP than the one it's originally linked to, the relative address calculation becomes invalid.
I've faced such a situation while writing my kernel head, which was physical-addresses linked, but the portion of it calling the C entry point was run using a virtualized (different) %ip. A solution was getting rid of %IP-relativeness all together and use a near absolute indirect jump (opcode = FF):
Hope that helps ..
Thanks a lot, but could you please show me the NASM (32 bit) equivalent to the code you posted?
Re: Triple fault upon call to extern function
Posted: Mon Apr 12, 2010 1:49 pm
by Gigasoft
No, that's 64 bit. It should be:
However, this is just if the address of the jmp instruction is different from what it was when linking, and the address of the kernel label is the same. I doubt this is the case here. Remapping the kernel to a different address wouldn't work with the linking method you described.
Try setting a breakpoint on the protectedMode label. You should be able to generate a program listing that tells you where it is, if there are GCC and LD options for it. Then, step through the jmp instruction and check where it ends up. Check if this area contains the expected code.
Re: Triple fault upon call to extern function
Posted: Tue Apr 13, 2010 9:00 am
by Benjamin1996
Gigasoft wrote:No, that's 64 bit. It should be:
However, this is just if the address of the jmp instruction is different from what it was when linking, and the address of the kernel label is the same. I doubt this is the case here. Remapping the kernel to a different address wouldn't work with the linking method you described.
Try setting a breakpoint on the protectedMode label. You should be able to generate a program listing that tells you where it is, if there are GCC and LD options for it. Then, step through the jmp instruction and check where it ends up. Check if this area contains the expected code.
Alright then Gigasoft, it seems that you were right. Remapping the kernel didn't work. But, I downloaded gdb.exe, and I typed "file bootloader.elf" and then "break protectedMode". This outputted:
And after that I got lost trying to follow your instructions.. could you please be a little more specific?
Re: Triple fault upon call to extern function
Posted: Tue Apr 13, 2010 11:17 am
by Solar
Grab a GDB tutorial from somewhere in the internet, and experiment a bit with some normal (userspace) applications, until you are confident in your use of this tool.
This is not wasted time. I know you'd love to get on with your bootloader, but do take the time to get to know GDB.
Believe me, the kind of programming we do is very hard without the support of a decent debugger, and while GDB might have an air of the eighties about it, it's easily one of the most powerful debuggers available once you got to master it.
Re: Triple fault upon call to extern function
Posted: Tue Apr 13, 2010 12:49 pm
by Gigasoft
I haven't used GDB, so I can only help you with using the debugger inside Bochs. When you link the program, you should use option -Map followed by a filename. For example, "-Map kernel.map". Then you look in this file for the symbol protectedMode (you may have to declare it to be global first). Then, in the Bochs debugger, you could enter "vb Segment:Offset", where Segment is the code selector you use when jumping to protectedMode, and Offset is the offset found in the map file. Then, enter the command "c", and it should stop at the correct location. Then, enter "s" to step until the jmp instruction has been executed. Note the value of EIP before and after the jmp, and check if the code jumped to is correct.
Re: Triple fault upon call to extern function
Posted: Wed Apr 14, 2010 1:48 pm
by Benjamin1996
Gigasoft wrote:I haven't used GDB, so I can only help you with using the debugger inside Bochs. When you link the program, you should use option -Map followed by a filename. For example, "-Map kernel.map". Then you look in this file for the symbol protectedMode (you may have to declare it to be global first). Then, in the Bochs debugger, you could enter "vb Segment:Offset", where Segment is the code selector you use when jumping to protectedMode, and Offset is the offset found in the map file. Then, enter the command "c", and it should stop at the correct location. Then, enter "s" to step until the jmp instruction has been executed. Note the value of EIP before and after the jmp, and check if the code jumped to is correct.
Alright, first of all, I've made a few changes to the 32 bit "protectedMode" function. So it now looks like this:
Code: Select all
[bits 32]
[global loadKernel]
loadKernel:
mov ax, 0x0010
mov ds, ax
mov ss, ax
mov esp, 0x90000
jmp 0x0008:0x1000
Now the error message in "bochsout.txt" is:
Code: Select all
00014070914i[CPU0 ] 0x0000000047e87c5f>> (invalid) : FFFF
00014070914e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
And this is one of the .text sections in "kernel.map":
Code: Select all
.text 0x00007c00 0x400
*(.init)
*(.text)
.text 0x00007c00 0x200 bootloader.elf
0x00007c6b loadKernel
.text 0x00007e00 0x15 kernel.elf
0x00007e00 kernel
And now, this is the output of the final 's' command:
Code: Select all
(0) [0x00007c78] 0008:0000000000007c78 (unk. ctxt): jmp far 0008:00001000 ;
ea001000000800
Re: Triple fault upon call to extern function
Posted: Wed Apr 14, 2010 2:34 pm
by Gigasoft
Why are you jumping to 0x1000? According to the map file, "kernel" is at 0x7e00. What you had initially should work, assuming that you have loaded the sectors to the correct addresses. Note that loading the sectors to address 0x1000 won't work, since the kernel assumes that it resides at 0x7e00. Try with "jmp kernel" and see what happens when you step through the jmp. EIP becoming 47e87c5f could mean that an exception occurs, and you haven't initialized the IDT. If you load IDTR with a limit of 0, Bochs should tell you which exception occurred. Maybe it would be easier to diagnose if you post the entire bootloader.asm or os.bin.
Re: Triple fault upon call to extern function
Posted: Thu Apr 15, 2010 10:12 am
by Benjamin1996
Gigasoft wrote:Why are you jumping to 0x1000? According to the map file, "kernel" is at 0x7e00. What you had initially should work, assuming that you have loaded the sectors to the correct addresses. Note that loading the sectors to address 0x1000 won't work, since the kernel assumes that it resides at 0x7e00. Try with "jmp kernel" and see what happens when you step through the jmp. EIP becoming 47e87c5f could mean that an exception occurs, and you haven't initialized the IDT. If you load IDTR with a limit of 0, Bochs should tell you which exception occurred. Maybe it would be easier to diagnose if you post the entire bootloader.asm or os.bin.
Oops, my bad. - That's because I forgot to tell you that I loaded kernel.o into 0x1000.
Anyway, I've changed it (again
), so here's the full "bootloader.asm":
Code: Select all
[bits 16]
boot:
mov ax, 0x0000
mov ds, ax
call clearScreen
call resetCursor
mov si, loadingKernel
call print
call resetDiskSystem
call enableA20
call installGDT
call protectedMode
protectedMode:
cli
mov eax, cr0
or eax, 0x0001
mov cr0, eax
jmp 0x0008:loadKernel
installGDT:
cli
lgdt[GDT]
sti
ret
enableA20:
mov ax, 0x2401
int 0x0015
jc enableA20
ret
resetDiskSystem:
xor ax, ax
int 0x0013
jc resetDiskSystem
ret
print:
lodsb
cmp al, 0
jz donePrinting
mov ah, 0x000e
int 0x0010
jmp print
donePrinting:
ret
resetCursor:
mov ah, 0x0002
mov bh, 0x0000
mov dh, 0x0000
mov dl, 0x0000
int 0x0010
ret
clearScreen:
mov ax, 0x0600
mov cx, 0x0000
mov dx, 0x1950
mov bh, 0x0007
int 0x0010
ret
[bits 32]
[global loadKernel]
loadKernel:
mov ax, 0x0010
mov ds, ax
mov ss, ax
mov esp, 0x90000
jmp 0x0008:0x7e00
GDTNull:
dd 0
dd 0
GDTCode:
dw 0x0FFFF
dw 0
db 0
db 10011010b
db 11001111b
db 0
GDTData:
dw 0x0FFFF
dw 0
db 0
db 10010010b
db 11001111b
db 0
endOfGDT:
GDT:
dw endOfGDT - GDTNull - 1
dd GDTNull
loadingKernel db "Loading kernel..", 0dh, 0ah, 0
times 510 - ($ - $$) db 0
dw 0xaa55
Full "kernel.asm":
Code: Select all
[bits 32]
[global kernel]
kernel:
mov edi, 0xb8000
mov byte [edi], 'K'
mov byte [edi + 1], 0x0007
hlt
Full "build.bat":
Code: Select all
@echo off
nasm -f elf bootloader.asm -o bootloader.elf
nasm -f elf kernel.asm -o kernel.elf
ld -o kernel.o kernel.elf
ld -Ttext 0x7c00 -Map os.map -o os.o bootloader.elf kernel.elf
objcopy -R .note -R .comment -S -O binary os.o os.bin
echo os.bin created!
rawwrite.exe
Full "os.bin" opened in Notepad:
Code: Select all
¸ ŽØèU èG ¾|è5 è+ è è è ú Àf
"Àêk| ú—|ûø$ÍrùÃ1ÀÍrúì< t´Íëõô· ¶ ² Íø ¹ ºP·ÍÃf¸ ŽØŽÐ¼ ê ~ ÿÿ šÏ ÿÿ ’Ï | Loading kernel..
Uª¿ € ÆKÆGôÿÿÿÿ ÿÿÿÿ
Some of "os.map":
Code: Select all
Adressen på sektionen .text sat til 0x7c00
LOAD bootloader.elf
LOAD kernel.elf
0x000001f0 . = SIZEOF_HEADERS
0x00001000 . = ALIGN (__section_alignment__)
.text 0x00007c00 0x400
*(.init)
*(.text)
.text 0x00007c00 0x200 bootloader.elf
0x00007c6b loadKernel
.text 0x00007e00 0xd kernel.elf
0x00007e00 kernel
And finally the error message in "bochsout.txt":
Code: Select all
00014073431i[CPU0 ] 0x000000000000fda8>> int1 : F1
00014073431e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Now, the funny thing is that it runs without crashing in Microsoft Virtual PC and on real hardware, BUT, even though it doesn't crash, it doesn't execute the "kernel" function..??