Hey everybody,
I have two questions about moving memory. For each, I've coded up a little proc that I'm wondering if ppl have suggestions for shrinking code/time:

1) I have an array of strucs and each struc is 316 bytes. When sorting the info, I have to exchange two elements. So I coded a SwapEntries proc using the stack. The other thing I was thinking was to use registers instead. But will this give me any better performance?



SwapEntries PROC uses esi edi lpOne,lpTwo:DWORD
mov eax,316
shr eax,2
mov esi,lpOne
mov edi,lpTwo
@@: push DWORD PTR [esi]
push DWORD PTR [edi]
pop DWORD PTR [esi]
pop DWORD PTR [edi]
add esi,4
add edi,4
dec eax
jnz @B
ret
SwapEntries ENDP



2) In another array :) I'm storing QWORDs. The array is to be sorted least to greatest so I can do a search on it easily enough. Every once in awhile I need to throw in a new QWORD. Suppose edx:eax has the QWORD and esi is pointing to the place where I want to insert the value. Conveniently, the array is termated by a null entry. This is what I'm thinking:



mov esi,insert_address
mov edx,value_hi
mov eax,value_lo
@@: xchg eax,[esi]
xchg edx,[esi+4]
add esi,8
test eax,eax
jnz @B


i.e., I just keep exchanging values until I reach the end of the struc.

Any ideas or optimizations are welcome.

Thanks for reading :)

--Chorus
Posted on 2002-07-20 18:44:12 by chorus
Well for the first an arry of DWORD pointers to each struct would mean you wouldn't have to shift a whole 316 bytes for each operation, that would mean a big saving.

For the second one a linked list might be a better solution.

Though if you'd rather not go down that road then perhaps the following algo might be faster. Image the following sorted array, each letter is a QWORD

ABCFGH

Lets say you want to add 'E'. Its probaly better to start from the back and move QWORDs backwards rather xchgs which are very slow. ie,

Step 1: ABCFGHH
Step 2: ABCFGGH
Step 3: ABCFFGH
Step 4: ABCEFGH

In both problems you'd be much better off using mmx, and if you can, move two QWORDs together to allow pairing, I think.
Posted on 2002-07-20 19:01:22 by Eóin
Thanks for your reply :)

For the first array, I decided not to use an index or a rank table b/c I didn't want to use any more memory. I wanted something that was more "in place" so I'm exchanging the whole strucs. Maybe I'll reconsider... index tables might offer more flexibility in the future.

As for the second array, I thought that moving data "backwards" wasn't very optimal. I understand that the xchgs aren't the best (Agner's manual says there's a lock prefix on xchg r/m) but wouldn't reading/writing forward help? Or is the xchg that bad? I guess the easy way to find out is just to test it :)


Also, I'll look into the MMX instructions,

Thanks again
--Chorus
Posted on 2002-07-20 19:12:21 by chorus
1) I go with E?in here, you don't want to be moving around 316 bytes unless it is only done once and you need to access the structures linearly for some weird algo that is used throughout the program. Just use a list of pointers and sort the pointer list.

2) Just keep a count of how big the array is and use a REP MOVSD. If you have the index into the array, then with the size of the index you can know how many items you need to move at the end to make space for the item. Of course, if your going to be working with millions of items, then another method is certainly better than this advice.
Posted on 2002-07-20 19:22:58 by bitRAKE