[Back to DATATYPE SWAG index] [Back to Main SWAG index] [Original]
{
From: ae723@FreeNet.Carleton.CA (Brent Beach)
>>> I am looking for a *fast* routine that can move more than 64k on any
>>> 80x86.
>> A loop using movsb is limited to 64K, but movsw can move 128K at a time.
>> 2 movsb loops can move 128K. 3 can do 196K, see where I'm going?
>
>MOVSW cannot move more than 64k. It is limited to 64k by the segmented
>architecture. So, to move more than 64k, several MOVSW are necessary. My
>problem is to find a routine in which this is done in a clever way. In fact,
>I know that I would not come up with a clever coding, so I hope that an asm
>guru somewhere has already done it...
You can never move 64KB in a single REP MOVSx instruction.
First, the MOVSx instructions only update the offsets, not the
segment registers, so 64KB is a maximu. Second, you run into
problems when the offset is $FFFF. Third, you can move even
less if the original addresses do not both have offset 0.
To handle all cases, you should try for moving a little less.
The following moves only 63KB. You could move 64K-16 bytes. I
tested this routine with the longtype array upperbound 16 (it
works with any multiple of 16).
By using a fast move for 63KB you gain almost all the speed you
can; it is probably not worth writing the glue code in ASM.
The speed gain over the builtin MOVE procedure is around 38% on
my machine (486/33). A test program ran for 2.58 seconds with
ASM, 4.17 seconds with MOVE.
}
procedure
movelong( fromp : pointer;
top : pointer;
len : longint);
{--------
long mover
- assumes from and to do not overlap (to not in from) }
type
longtype = array[1 .. 63 * 1024] of char;
longtypeptr = ^ longtype;
ptrrec = record
ofs, seg : word; end;
const
longtypelen = sizeof(longtype);
begin
{ fix the pointers: offsets between 0 and 15 }
inc(ptrrec(fromp).seg, ptrrec(fromp).ofs div 16);
ptrrec(fromp).ofs := ptrrec(fromp).ofs and 15;
inc(ptrrec(top).seg, ptrrec(top).ofs div 16);
ptrrec(top).ofs := ptrrec(top).ofs and 15;
{ move pieces }
while len > sizeof(longtype) do begin
{ faster than: move(fromp^, top^, sizeof(longtype)); }
asm
push ds
lds si,fromp
les di,top
mov cx,(longtypelen / 2)
cld
rep movsw
pop ds
end;
dec(len, sizeof(longtype));
inc(ptrrec(fromp).seg, sizeof(longtype) div 16);
inc(ptrrec(top).seg, sizeof(longtype) div 16);
end;
if len <> 0 then
{ faster than: move(fromp^, top^, len); }
asm
push ds
lds si,fromp
les di,top
mov cx,word(len)
shr cx, 1
cld
jnc @wordmove
movsb
@wordmove:
rep movsw
pop ds
end;
end;
[Back to DATATYPE SWAG index] [Back to Main SWAG index] [Original]