Page 1 of 1

Wrong address of DS segment in protected mode

Posted: Tue Nov 12, 2013 6:13 pm
by yee1
Hi Friends. I have problem with my DS segment while I am in protected mode.

Code: Select all

program_start:

; prepare segments for PM and enter pm, load new segments by selectors etc...

mov byte al, [my_number]

program_size dw $-program_start

data_start:
my_number db 62h
size_data dw $-data_start

ds segment starts at kernel_offset_in_memory+program_size

nasm generates wrong memory reference for instruction
mov byte al, [my_number]

for [my_number] it generates wrong memory reference of my_number and result is wrong becouse my_number_address = my_number-program_size

i can't make equal cs and ds segment base address becouse it will be segment violation


how to deal with it ? i can not access correctly any data from ds without making magic tips like
mov byte al, [my_number-program_size]

is the only way to solve it to do it like this ? :

Code: Select all

jmp program
data:
;data here
data_size dw $-data

program:
;program code here
program_size dw $-program
only this way ? or is there another way to solve it ?

thank you

Re: Wrong address of DS segment in protected mode

Posted: Tue Nov 12, 2013 10:18 pm
by mrstobbe
In protected mode DS should equal the offset to the data segment you care about in your GDT, not some kind of absolute segment. Same goes for all the rest of the segment registers. Presuming you have a GDT with two segments (the first for code, the second for data), CS should be 0x08 (relative offset within the GDT pointing to the code segment just after the null segment), while DS/ES/SS/etc should be 0x10 (relative offset again, just after the code segment).

Make sense, or am I reading your problem wrong?

Re: Wrong address of DS segment in protected mode

Posted: Wed Nov 13, 2013 7:49 am
by yee1
mrstobbe wrote:In protected mode DS should equal the offset to the data segment you care about in your GDT, not some kind of absolute segment. Same goes for all the rest of the segment registers. Presuming you have a GDT with two segments (the first for code, the second for data), CS should be 0x08 (relative offset within the GDT pointing to the code segment just after the null segment), while DS/ES/SS/etc should be 0x10 (relative offset again, just after the code segment).

Make sense, or am I reading your problem wrong?
Seems so, becouse my problem is that:
my kernel is loaded into 0x8000 memory space

cs is set directly at the begining of kernel (0x8000)

after program code space, there is data (ds) space

the problem is that when i make some "variable" at DS like

Code: Select all

data_seg:
myInfo db 81h
ds_size dw $-data_seg
and CS segment size is 100h,
then DS base address is like 0x8000+0x100 = 0x8100.

then if i want to get value of myInfo I would use this instruction

Code: Select all

mov byte al, [myInfo]
it would do somephing like this (pseudocode like):
mov byte al, [ds:0x0] , right ?
but in my kernel it does not
it do somephing like that:
mov byte al, [ds:0x100]

it should do ds:0 not ds:0x100
i don't know what i did wrong
i have never had such problem
there were never such problem when accessing variables of DS segment, seems to be some kind of NASM fail, but i really don't know

i have checked it after i enter pm mode and this problem also occurs, it should accesss myInfo variable by ds:0 and it access it by ds:0x100

why ?

Re: Wrong address of DS segment in protected mode

Posted: Wed Nov 13, 2013 8:54 am
by Combuster
Your main problem is that you're trying to convince your toolchain (GCC and LD, I presume) to emit code for a segmented memory model. While you can pull off this particular instance with some hardcore tricks, your tools assume that segmentation is not applied altogether and that all segments have a base of zero. Thus if DS shares the base with CS and the actual data section comes 256 bytes into the app, then reading from [DS:0x100] actually is the correct address.

So if you want to use segment:0x0 for both the start of the code and start of the data, the only option you have is to trick the linker into putting both the code and data into virtually overlapping areas (link address) but tell your binary loader to put the two parts into different places in memory (load address).

You can only separate code and data that way. Any attempt at having even more distinct segments gets foiled by the compiler randomly substituting SS with DS or ES, making that a practical impossibility. Most people simplify this to the DS=ES=SS rule.



tl;dr: what you're trying is asking for trouble. Don't use segments with base != 0 in protected mode unless you know exactly what you're doing.