Page 1 of 1

ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 2:03 pm
by smoothCoder
In the Intel-manual, one can read that ES segment register is ignored in long mode.
What I have done is:
Enter in long mode in the boot loader, then used INSW instruction with inicial value in EDI 100000h.
Second stage loader load fine, executes fine and jumps work fine, but atempting to read data from above [100000h] memory returns all 0s. This confused me because the second stage loader resides there and work fine, so instructions are fetched. The paging consist at this point of a normal page entry of 2MB.
When I just had no more things to try, have set ES to 0 in the bootloader just before the primitive PIO ATA driver.(the driver worked alredy in long mode(I expected initially the INSW to use RDI))
Now, when setting ES to 0, all works fine.
:?:

Re: ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 3:15 pm
by gerryg400
Perhaps you're still in compatibility mode. When you follow the procedure to enter long mode, did you do a far jmp to your 64bit code segment after following all other steps ?

Code: Select all

		ljmpl	$0x8, $(code_seg_64)

.code64
code_seg_64:
Until you do the far jmp you are still in 32 bit mode.

Re: ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 4:11 pm
by smoothCoder
I tested the long mode enabled bit and it's enabled. I will restore the system to previous state and then will try again. Lately I tend to consider virtualization software bugs and programer errors(mine) equally possible.

Re: ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 4:13 pm
by gerryg400
smoothCoder wrote:I tested the long mode enabled bit and it's enabled. I will restore the system to previous state and then will try again. Lately I tend to consider virtualization software bugs and programer errors(mine) equally possible.
It's not enough. Even though the bit is set, you must also jump to a 64 bit code segment. Did you do that ?

Re: ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 5:12 pm
by smoothCoder
pfffff...
This is very frustrating.
I have done the far-jump to the 64-bit code segment. But now with the system restored, independently of the value in the ES register I have the next problem:

Code: Select all

cmp EAX, [EBX]
je jump_PCI_database_match
here je and jne make the same jump to the same label.

Now I will revise the entire code, and hopefully I'll see it.

Re: ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 6:02 pm
by smoothCoder
Ok, definitively the problem was with the "rep insw" instruction. when I used the "rep insw" instruction, I needed to set the ES reg to 0 in order to can read the memory above 100000h(weird).
And the above code:

Code: Select all

cmp EAX, [EDI]     ;The truth is that I used EDI reg to reference memory
;here je and jne gives the same jump
I replaced it with:

Code: Select all

cmp EAX, [EBX]            ;When no using EDI as mem ref, the code work fine
;here the jcc behaves as expected
But the definitively solution for this problem was to use an simple kind of function in the place of "rep insw" instruction:

Code: Select all

xor ECX, ECX
inc CH
read_one_sector:
in AX, DX
mov [EDI], AX
inc EDI
inc EDI
dec CX
jnz read_one_sector
It seems that the "rep insw" instruction has broken the EDI reg completely.

Re: ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 6:57 pm
by NickJohnson
I thought you were writing 64 bit code: why are you using EDI to store pointers?

Re: ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 7:06 pm
by gerryg400
It seems that the "rep insw" instruction has broken the EDI reg completely.
Have you ever run Windows or Linux on this processor? Surely if the processor were this broken you would know by now. I feel you haven't initialised the processor correctly. BTW, have you enabled a20 correctly ?

Re: ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 7:17 pm
by smoothCoder
NickJohnson:
This is a mine custom I guess. Now the code is in development stage. Optimizations will take place when code it's working.
gerryg400 wrote:
It seems that the "rep insw" instruction has broken the EDI reg completely.
Have you ever run Windows or Linux on this processor? Surely if the processor were this broken you would know by now. I feel you haven't initialised the processor correctly. BTW, have you enabled a20 correctly ?
I rely on BIOS to do this for me. I really need to spare every byte in the boot loader(first stage/512 bytes).

And yes, I never had problems on this machine executing OSes in the real hardware. But I have done a looot of tests and my previous post is exactly what I have got in virtualized environment.(tests about EDI, rep insw)

Re: ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 7:34 pm
by gerryg400
Which virtualised environment are you using ?

Re: ES segment register behaves unexpectedly

Posted: Fri Sep 17, 2010 7:40 pm
by smoothCoder
Microsoft Hypervisor. Earlier I often used it in networks training stuff and never disapointed me when used microsoft OSes.

Re: ES segment register behaves unexpectedly

Posted: Sat Sep 18, 2010 5:15 pm
by NickJohnson
smoothCoder wrote:NickJohnson:
This is a mine custom I guess. Now the code is in development stage. Optimizations will take place when code it's working.
This is not an optimization: it's probably the source of your bug! EDI is a 32 bit register, so it should not (be attempted to) be used to store 64 bit pointer values. If you're truly in long mode, rep insw would be reading the upper 32 bits of RDI as well, which could be anything! Perhaps RDX just happened to be cleared, giving you the impression that EDI was "broken" and EBX was "not broken". Use RDI, or at least clear it before using EDI.

Re: ES segment register behaves unexpectedly

Posted: Sat Sep 18, 2010 5:29 pm
by smoothCoder
NickJohnson wrote:
smoothCoder wrote:NickJohnson:
This is a mine custom I guess. Now the code is in development stage. Optimizations will take place when code it's working.
This is not an optimization: it's probably the source of your bug! EDI is a 32 bit register, so it should not (be attempted to) be used to store 64 bit pointer values. If you're truly in long mode, rep insw would be reading the upper 32 bits of RDI as well, which could be anything! Perhaps RDX just happened to be cleared, giving you the impression that EDI was "broken" and EBX was "not broken". Use RDI, or at least clear it before using EDI.
Thanks!
When I code "mov EDI, 100000h", the upper 32 bits of the RDI are cleared automaticaly. And if I need an pointer to below the 4GB space, the only difference between "mov EAX, [EDI]" and "mov EAX, [RDI]" is one byte diference in the size of the opcode produced, and shorter code is better always. This is why I consider this as optimization stuff.

Re: ES segment register behaves unexpectedly

Posted: Sat Sep 18, 2010 5:55 pm
by NickJohnson
I guess you're right: mov EDI does clear RDI as well, so that wouldn't cause a problem. Still, you want to avoid premature optimization like this.

Re: ES segment register behaves unexpectedly

Posted: Sat Sep 18, 2010 6:15 pm
by smoothCoder
As long as my code do what I expect to do, I'm happy.
I guess latter I will try again to use "rep insw" because is shorter way to do the same. Now I load the e820 output to a known place, enter in long mode and load second stage. This leave me with only 15 bytes free place. There are more things I want to do in the 1 stage(512B) loader, so probably latter I will try to make "rep insw" to work correctly and to enter directly in long mode, this way I will spare two GDT entryes and a few lines of code to enter 32 bit mode. I tried to enter in long mode directly but not worked for me. But this latter, now I'm doing another stuff.