Access Variables in Kernel
Access Variables in Kernel
I have a kernel loaded a 0x9000:0 but I can't seem to access variables in the .data section. All my code is in assembler at the moment. Is this a problem with the GDT? I've also seen a few asm kernels using a linker script? Could that be the problem because I dont have one? Also, a cpu_dump from the bochs debugger shows DS valid=7, whereas all the other segments are valid=1, could this be the problem? Thanks
Re:Access Variables in Kernel
Hi,
Your problem may also be your boot loader (is the .data section loaded?), the data segment register contents (DS, ES), the GDT contents (correct bases?). Another possibility is the ORG you told the assembler (e.g. if CS base is 0x90000 you may have told the assembler to use ORG 0, so that if data segments have base = 0 data offsets are wrong).
Another problem you are likely to have is that most BIOS's have an EBDA (extended BIOS data area) that is below the video display memory. Depending on how big your kernel is it may overwrite the EBDA and/or the video display memory and/or the video BIOS. For example, if your kernel uses 96 Kb (.text + .data + .bss) you will overwrite the video display memory from 0xA0000 to 0xB0000. If the kernel is using a text video mode (which starts at 0xB8000) you might not notice this on the screen....
Cheers,
Brendan
I don't use a linker script either (my kernel is 100% NASM source which is assembled directly into binary format). If you're assembler is generating an object file instead of a binary then you may need a linker script. This would depend on which assembler, boot loader and linker and how they are used.Pulser wrote: I have a kernel loaded a 0x9000:0 but I can't seem to access variables in the .data section. All my code is in assembler at the moment. Is this a problem with the GDT? I've also seen a few asm kernels using a linker script? Could that be the problem because I dont have one? Also, a cpu_dump from the bochs debugger shows DS valid=7, whereas all the other segments are valid=1, could this be the problem? Thanks
Your problem may also be your boot loader (is the .data section loaded?), the data segment register contents (DS, ES), the GDT contents (correct bases?). Another possibility is the ORG you told the assembler (e.g. if CS base is 0x90000 you may have told the assembler to use ORG 0, so that if data segments have base = 0 data offsets are wrong).
Another problem you are likely to have is that most BIOS's have an EBDA (extended BIOS data area) that is below the video display memory. Depending on how big your kernel is it may overwrite the EBDA and/or the video display memory and/or the video BIOS. For example, if your kernel uses 96 Kb (.text + .data + .bss) you will overwrite the video display memory from 0xA0000 to 0xB0000. If the kernel is using a text video mode (which starts at 0xB8000) you might not notice this on the screen....
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Access Variables in Kernel
Ok... I'm going for the ORG 0x7c00 approach in my boot loader. My GDT is:
I load my kernel to 0x90000 (ES -> 0x9000)
I disable interrupts...
Load my GDT
Enable protected mode, and far jump to 0x08:Pmode
Then:
And my kernel cant access its variables in the "[section .data]". Any hints would be very much appreciated. Thanks
Code: Select all
gdt: ; Very start of our GDT
gdt_null: ; Null Segment -> 4 Null Words
dw 0 ; Null Word
dw 0 ; Null Word
dw 0 ; Null Word
dw 0 ; Null Word
gdtCode: ; Code Segment
dw 0xFFFF ; Limit -> 4GB
dw 0x0000 ; Base Address -> 0 (Start of memory)
db 0x00 ; Continue base address
; Access flag -> 0, Readable Segment -> 1, Conforming -> 0
; Code Segment -> 1, Code/Data Segment -> 1, Privelage level -> 00
; Present -> 1
db 10011010b ; Above flags
; Last bits of segment limit -> 1111, Ignored -> 0, Reserved -> 0,
; 32-bit code -> 1, Granularity -> 1,
db 11001111b ; Above flags
db 0x00 ; Remaining base address
gdtData: ; Our data segment
dw 0xFFFF ; Limit -> 4GB
dw 0x0000 ; Base Address -> 0 (Start of memory)
db 0x00 ; Continue base address
; Accessed -> 0, Writeable Segment -> 1, Expand -> 0 (down),
; Code Segment -> 0 (data), Code/Data Segment -> 1, Privelage -> 00
; Present -> 1
db 10010010b ; Above flags
; Last bits of segment limit -> 1111, Ignored -> 0, Reserved -> 0,
; 32-bit code -> 1, Granularity -> 1
db 11001111b ; Above Flags
db 0x00 ; Remaining base address
gdtEnd: ; End of our GDT
gdtDesc: ; GDT Descriptor
dw gdtEnd-gdt ; Size of GDT in bytes
dd gdt ; GDT's memory address
I disable interrupts...
Load my GDT
Enable protected mode, and far jump to 0x08:Pmode
Then:
Code: Select all
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
jmp 0x90000 ; Jumps to the fully loaded kernel
Re:Access Variables in Kernel
Hi,
You didn't mention which assembler and how it's invoked. If you are using NASM (source code looks like NASM), then:
nasm -o kernel.bin -f binary source.asm
would work and doesn't require a linker script (or linker).
If this is the case, then I'm lost (unless you're using paging?)
Cheers,
Brendan
This all looks correct, as long as you use "ORG 0x90000" for your kernel.Pulser wrote: Ok... I'm going for the ORG 0x7c00 approach in my boot loader. My GDT is:
I load my kernel to 0x90000 (ES -> 0x9000)
You didn't mention which assembler and how it's invoked. If you are using NASM (source code looks like NASM), then:
nasm -o kernel.bin -f binary source.asm
would work and doesn't require a linker script (or linker).
If this is the case, then I'm lost (unless you're using paging?)
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.