Page 1 of 1
Memory Copying
Posted: Thu Dec 28, 2006 11:16 am
by Tolga
Hi.
I need memory copying between different segments.
Example, i will copy 100 byte between GDT Entry 1 Segment and GDT Entry 5 Segment.
I think that if i change ds to source memory selector and es to destination memory selector. And i will use REP MOVSB. But if task changes when copying, this may be create an error.
How can i do this? (Im using GCC)
Re: Memory Copying
Posted: Thu Dec 28, 2006 11:43 am
by Brendan
Hi,
Tolga wrote:I need memory copying between different segments.
Example, i will copy 100 byte between GDT Entry 1 Segment and GDT Entry 5 Segment.
I think that if i change ds to source memory selector and es to destination memory selector. And i will use REP MOVSB. But if task changes when copying, this may be create an error.
If your task switch code saves and restores the segment registers, and if your memory copying code saves and restores the original segment registers, and if your IRQ handlers can handle interrupting code that's using different segment registers, then everything should work fine (as long as the memory copy code itself is done with assembly, as it'd confuse GCC completely).
Also, you can use a segment override for "rep movs". For example, use FS:ESI as the source address (GCC shouldn't touch FS or GS). Unfortunately you can't override the destination, which always uses ES. Depending on a lot of different things, you might be able to use something like:
Code: Select all
__volatile__ __asm__ (
"pushl es\n\t"
"movw $0x28,%ax\n\t"
"movw %ax,%es\n\t"
"movw $0x08,%ax\n\t"
"movw %fs,%ax\n\t"
"fs rep movsb\n\t"
"popl es\n\t"
: /* no output registers */
: "c" (count), "S" (src), "D" (dest)
: "%ecx", "%esi" , "%edi", "memory"
);
For this you'll need 3 variables ("int count", "void *src" and "void *dest") set appropriately before this code is used. It also wouldn't be hard to modify the above to save and restore FS (and/or use DS instead of FS).
Of course the code above should also be tested before you use it - I rarely use GCC or AT&T syntax, so some bugs may have found their way into it...
The other option is to have a third segment that is large enough to access both areas - that way you could copy from ES:ESI to ES:EDI and only mess with one segment register.
Tolga wrote:How can i do this? (Im using GCC)
Hmm, segmentation and GCC - a rather unusual combination...
Cheers,
Brendan
Posted: Thu Dec 28, 2006 12:03 pm
by earlz
well gas doesn't support segment overrides so I guess your only choice would be..(add \n's to the end of every line...)
Code: Select all
__asm(".intel_syntax noprefix\n"
"cli\n" //keep something from happening while were doing this
"push ds\n"
"mov ax,0x8\n" //our source segment
"mov ds,ax\n"
"mov ebx,0x100\n" //our source offset of segment
"mov ecx,20\n" //how many bytes to copy
"mov edi,0x300\n" //our destination offset
"do_loop:\n"
"mov dl,[ebx]\n" //this defaults to use DS so we use the segment loaded earlier
"push ds\n"
"mov ax,0x20\n" //our destination segment
"mov ds,ax\n"
"push ebx\n"
"mov ebx,edi\n"
"mov [ebx],dl\n"
"add edi,1\n" //increment destination pointer
"pop ebx\n" //restore ebx to source offset
"pop ds\n" //restore ds to source segment
"add ebx,1\n" //increment source pointer
"loop do_loop\n" //then we do it again..
"pop ds\n" //pop the ds of whoever called this
"sti\n"
".att_syntax\n"); //we do this so gcc stuff wil compile..
I didn't try to compile it, also if your wanting to be able to do stuff dynimically like memcpy_segments(dest_seg,dest_offset,src_seg,src_offset); then you'll have to look up how to get arguments off the stack in asm..\
edit:
he beat me too it.. I'd use his, it's more optimized..(fact, think I might use his code, for myself..)
Posted: Thu Dec 28, 2006 12:27 pm
by Tolga
What is the problem between segmentation and GCC? I will use paging but i want to learn this.
Other question, does this codes change with paging?
Posted: Thu Dec 28, 2006 12:30 pm
by INF1n1t
Tolga wrote:What is the problem between segmentation and GCC? I will use paging but i want to learn this.
Other question, does this codes change with paging?
I think the problem is that some compilers generate code for flat memory model and not for the segmentation-type. And it happens that GCC is that kind of compiler!
Posted: Thu Dec 28, 2006 12:34 pm
by earlz
I think the new watcom C supports 32bit segmentation, like the far stuff.
The real problem with segmentation in GCC is theirs no 32bit far data types, and gas doesn't support segments very well
for example you can't do mov eax,[10:40] it doesn't compile..(not sure on if att is anybetter though..)
Posted: Fri Dec 29, 2006 11:13 am
by Tolga
I have wrote this code for copying between two different segments. I dont know enough At&t assembly. So i dont sure the code. Can somebody try this code? Or if there are errors, can adjust them?
Thanks.
Code: Select all
// copy memory
void TSystem_Memory::CopyMemory( TTypeOfSegmentSelector SourceSegmentSelector, LONGWORD SourceAddress, TTypeOfSegmentSelector DestinationSegmentSelector, LONGWORD DestinationAddress, LONGWORD CopyLength ){
// variables
LONGWORD SourceSelector;
LONGWORD DestinationSelector;
// codes
// create selectors
// source selector
SourceSelector = SourceSegmentSelector.RPL + (SourceSegmentSelector.Table << 2) + (SourceSegmentSelector.Index << 3);
DestinationSelector = DestinationSegmentSelector.RPL + (DestinationSegmentSelector.Table << 2) + (DestinationSegmentSelector.Index << 3);
// copy
asm volatile(
// disable interrupts
"cli\n\t"
// save
"pusha\n\t"
"pushw %%ds\n\t"
"pushw %%es\n\t"
// adjust length
"movl %4, %%ecx\n\t"
// adjust registers
// source selector
"movw %0, %%ds\n\t"
// source address
"movl %1, %%esi\n\t"
// destination selector
"movw %2, %%es\n\t"
// destination address
"movl %3, %%edi\n\t"
// copy
"rep movsb\n\t"
// load
"popw %%es\n\t"
"popw %%ds\n\t"
"popa\n\t"
// activate interrupts
"sti\n\t"
// output
:
// inputs
: // source segment selector
"m" (SourceSelector),
// source address
"m" (SourceAddress),
// destionation segment selector
"m" (DestinationSelector),
// destination address
"m" (DestinationAddress),
// length
"m" (CopyLength)
);
}