Board index » delphi » need BP7-asm help

need BP7-asm help

To clear video memory very fast I wrote following procedure:
{*********************************************************}
{ fill memory with word value using 4 byte stepping
{ Call:    FillWord (dest, count, value);
{ Input:   dest:         destination
{          count: word;  number of double words
{          value: word;  fill value
{---------------------------------------------------------}
procedure FillDWord (var dest; count, value: word); assembler;
asm
  les  di, dest       {es,di = dest}
  mov  cx, count      {cx = count}
  mov  ax, value      {ax = value}
  db   66h
  shl  ax, 16         {eax hi = value}
  mov  ax, value      {eax low= value}
  db   66h
  rep  stosw          {fill with double word stepping}
end;

Now I want set memory with a longint value. But there is a problem.
How can I set longint value to register eax ???
{*********************************************************}
{ fill memory with given long value using 4 byte stepping
{ Call:    FillLong (dest, count, value);
{ Input:   dest;            destination
{          count: word;     number of double words
{          value: longint;  fill value
{---------------------------------------------------------}
procedure FillLong (var dest; count: word; value: longint); assembler;

asm
            les  di, dest    {es,di = dest}
            mov  cx, count   {cx = count}
  db 66h;   mov  ax, value   {eax = value}  !!! syntax error !!!
  db 66h;   rep  stosw       {fill with double word stepping}
end;

If you know it, PLEASE repost or send an email. Thanx Gerd

 

Re:need BP7-asm help


Quote
Gerd wrote:

> To clear video memory very fast I wrote following procedure:
> {*********************************************************}
> { fill memory with word value using 4 byte stepping
> { Call:    FillWord (dest, count, value);
> { Input:   dest:         destination
> {          count: word;  number of double words
> {          value: word;  fill value
> {---------------------------------------------------------}
> procedure FillDWord (var dest; count, value: word); assembler;
> asm
>   les  di, dest       {es,di = dest}
>   mov  cx, count      {cx = count}
>   mov  ax, value      {ax = value}
>   db   66h
>   shl  ax, 16         {eax hi = value}
>   mov  ax, value      {eax low= value}
>   db   66h
>   rep  stosw          {fill with double word stepping}
> end;

This code is very buggy, and I'd recommend some changes -- you're ignoring
the fact that there are an extra 16 bits in the extended registers, and
depending on what state the processor is in, you could be in for a minor
disaster.  Try this:

procedure fillword (var dest; count, value : word); assembler;

asm
  db 66h; xor   di,di      {clear EDI -- important!}
  db 66h; xor   cx,cx      {clear ECX -- important!}
          les   di,[dest]  {load pointer to memory to ES:[(E)DI]}
          mov   ax,[value] {get 16-bit value}
  db 66h; shl   ax,16      {shift into upper word}
          mov   ax,[value] {refresh low word}
          cld              {clear direction flag -- important!}
          mov   cx,[count] {load word count}
  db 66h; rep   stosw      {do the store}
end;

Note the changes here:  If the high word of EDI or ECX are set for a 32-bit
store, unpredictable things could happen.  Also, the direction flag MUST be
cleared.  If you enter this procedure when it's set, the rep stosd will count
EDI downward and make a mess of things.

Quote
> Now I want set memory with a longint value. But there is a problem.
> How can I set longint value to register eax ???

Here's a possible solution (haven't tested it, but it compiles):

procedure filldword (var dest; count : word; var value : longint); assembler;

asm
          push  ds         {save DS register -- required}
  db 66h; xor   si,si      {clear ESI}
  db 66h; xor   cx,cx      {clear ECX}
          mov   cx,[count] {load counter}
          cld              {clear direction flag}
          lds   si,[value] {get address of "value"}
          lodsw            {load the low word (comes first)}
          push  ax         {save it to the stack}
          lodsw            {load the high word}
  db 66h; shl   ax,16      {shift it into the upper word of EAX}
          pop   ax         {restore the low word}
          pop   ds         {... and DS}
  db 66h; xor   di,di      {clear EDI}
          les   di,[dest]  {get mem pointer into ES:[(E)DI]}
  db 66h; rep   stosw      {do the mem store}
end;

Quote
> If you know it, PLEASE repost or send an email. Thanx Gerd

--
Scott Earnest                      | _,-""-_,-""-_,-""-_,-""-_,-""-_,-" |
set...@ix.netcom.com (primary)     | We now return you to our regularly |
siny...@{*word*104}space.org (alternate) | scheduled chaos and mayhem. . . .  |

Re:need BP7-asm help


Scott Earnest <set...@ix.netcom.com> wrote in article
<3279ECB2....@ix.netcom.com>...

Quote
> Gerd wrote:
> > procedure FillDWord (var dest; count, value: word); assembler;
> > asm
> >   les  di, dest       {es,di = dest}
> >   mov  cx, count      {cx = count}
> >   mov  ax, value      {ax = value}
> >   db   66h
> >   shl  ax, 16         {eax hi = value}
> >   mov  ax, value      {eax low= value}
> >   db   66h
> >   rep  stosw          {fill with double word stepping}
> > end;

> This code is very buggy... Try this:
> procedure fillword (var dest; count, value : word); assembler;

> asm
>   db 66h; xor   di,di      {clear EDI -- important!}
>   db 66h; xor   cx,cx      {clear ECX -- important!}
>           les   di,[dest]  {load pointer to memory to ES:[(E)DI]}
>           mov   ax,[value] {get 16-bit value}
>   db 66h; shl   ax,16      {shift into upper word}
>           mov   ax,[value] {refresh low word}
>           cld              {clear direction flag -- important!}
>           mov   cx,[count] {load word count}
>   db 66h; rep   stosw      {do the store}
> end;

I don't agree; his original code looked OK, except for the CLD instruction,
and possibly for the way that REP MOVSD was encoded (it might have to
be REP; DB $66; STOSW; I don't have my reference material handy...)
The point is that STOSW will use DI (and CX) unless used in 32-bit
ADDRESSING mode, toggled by DB $67.

Chris.

Re:need BP7-asm help


Quote
Gerd wrote:

--snip--

Quote
> Now I want set memory with a longint value. But there is a problem.
> How can I set longint value to register eax ???
> {*********************************************************}
> { fill memory with given long value using 4 byte stepping
> { Call:    FillLong (dest, count, value);
> { Input:   dest;            destination
> {          count: word;     number of double words
> {          value: longint;  fill value
> {---------------------------------------------------------}
> procedure FillLong (var dest; count: word; value: longint); assembler;

> asm
>             les  di, dest    {es,di = dest}
>             mov  cx, count   {cx = count}
>   db 66h;   mov  ax, value   {eax = value}  !!! syntax error !!!
>   db 66h;   rep  stosw       {fill with double word stepping}
> end;

> If you know it, PLEASE repost or send an email. Thanx Gerd

The syntax error is due to the fact that you are trying to load a 16-bit
register (AX; the compiler doesn't know that the db 66h makes it into
EAX) with a 32-bit value.  All you need to do is type-cast the value
into a word to fool the compiler:

    db 66h;   mov  ax, word ptr [value]

This will correctly load EAX with the DWORD [value].  I know this works
on Turbo Pascal 6.0 because I do this sort of thing all of the time (use
32-bit registers in asm blocks); it should still work on Turbo/Borland
Pascal 7.

Hope this helps.

Will <lib...@ix.netcom.com>

Other Threads