How to change data segment? What am I doing wrong?

2.1k Views Asked by At

I am developing a 32 bit OS and have developed a working ELF loader that works just fine. Now I do not have paging enabled (I plan to later, but right now I am just trying to load kernel modules) and I am trying to execute modules at boot. Basically since again at this time multitasking is not fully implemented I just want to load each module, call init (which will install interrupt handlers and just set up what ever the module is for) and then exit and execute the next one. It works, but I can not do anything with pointers in the C program (because it still thinks it is using the kernels data segment). So basically what I want to do is make a new data segment that points to the modules .data segment in RAM. I am doing this by setting entry number 6 in the GDT like.

setGDTEntry(6, DataAddress,DataSize, 0xF2, 0xCF);

The setEntry method works just fine, it looks like

void setGDTEntry(int num, uint Base, uint limit, byte access, byte gran)

Again both work 100%, the problem that I am having occurs when I change the data segment selector. I am doing this in assembly, the ELFs entry point is stored in EAX.

mov ax, 30h ; This is 8 * 6, the GDT entry containing the new data segment
mov ds, ax ; set data segment
call address ; JUMP!!!!
mov ax, 0x10 ; Restore kernel data segment
mov ds, ax ; set data segment

This will cause my kernel to panic, giving CPU exception 0x6, invalid opcode. The source code for my C Program is just a hello world program that copies text into video RAM (nothing much to see.). Does anyone know what I am doing wrong? I am new to the whole concept of the GDT and segment selectors.......... And I can not have paging or multitasking enabled at this time, I really do not feel like explaining why....

1

There are 1 best solutions below

0
On

First of all, you need to set not only ds, but also es and ss. If you don't, some instructions will use ds.base as the segment base (e.g. mov eax, [ebx]), while others will use ss.base (e.g. mov eax, [ebp+8]) or es.base (e.g. rep movsd) and they will be different resulting in inconsistent addressing.

Another problem you're likely to be having is wrong cs (the invalid instruction exception is indicative of that). x86 code isn't position independent generally. Just like you have to create and use a separate data segment to compensate for the difference between where the data sections are loaded in the memory and where they are supposed to be in the memory (the various ELF headers/sections tell you that), you have to do the same for the code section. You can change cs using either a far call or a far jump or a far return.