delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/01/06/19:20:41

Message-ID: <32D192D7.4511@ix.netcom.com>
Date: Mon, 06 Jan 1997 16:03:35 -0800
From: Dan Mintz <danmintz AT ix DOT netcom DOT com>
Reply-To: danmintz AT ix DOT netcom DOT com
Organization: Private Party
MIME-Version: 1.0
To: djgpp AT delorie DOT com
Subject: Re: Intel ASM to AT&T ASM question
References: <01b9b9ca$9cccd040$aaf15ecf AT platko DOT ix DOT netcom DOT com> <5arf5r$lqn AT agate DOT berkeley DOT edu>

Eric J. Korpela wrote:
> 
> In article <01b9b9ca$9cccd040$aaf15ecf AT platko DOT ix DOT netcom DOT com>,
> Chuck Jarenski <3455245 AT popnet DOT ca DOT out DOT net> wrote:
> >I'm trying to convert the following code from More Tricks of the
> >Game-Programming Gurus into DJGPP.  I'm having a problem getting the code
> >in the book to work in the
> >AT&T syntax.  (Remember ScreenWidth is a 32bit int with the value of 640
> >and I am using near pointers with mem protection off.)
> >
> >       void vputpixel(int x, int y, char color, char far *vscreen)
> >       {
> >         asm {
> >           push es
> >           mov ax,[y]
> >           mov bx,320
> >           mul bx
> >           add ax,[x]
> >           les di,[vscreen]
> >           mov di,ax
> >           mov al,color
> >           stosb
> >           pop es
> >         }
> >       }
> 
> Here I go into tirade mode.  Not directed at you, but more toward
> programming book writers in general.  The big problem is that they
> make novices think that a compiler is incapable of optimizing something
> as simple as a putpixel routine.  There is no reason to resort
> to inline assembly.  The above would translate as....
> 
> void vputpixel(int x, int y, char color, char *vscreen)
> {
>   vscreen[y*320+x]=color;
> }
> 
> Run GCC on that and look at the output.  Compare it to the above.  GCC's
> output is better!  (Using mul to multiply by a constant!  Get real!)
> "Tricks of the Game Programming Gurus,"  heh.  More like "Tricks of the
> Writers Who Don't Know Anything About Programming."
> 
> Exit Tirade mode....
> 
> >My AT&T code:
> >
> >       void PutPixel(char *Buf, int X, int Y, char Color)
> >       {
> >         /* Places a pixel on the buffer at a X,Y location */
> >
> >       __asm__ __volatile__("
> >         pushl %%es
> >         movl %0 , %%eax\n
> >         movl $_ScreenWidth, %%ebx\n
> >         mull %%ebx\n
> >         addl %1, %%eax\n
> >         lesl %2, %%edi\n
> >         movl %%eax, %%edi\n
> >         movb %%al, %3\n
> >         stosb\n
> >         popl %%ss"
> >         :
> >         : "g" (Y), "g" (X), "g" (Buf), "g" (Color)
> >         : "memory"
> >         );
> >       }
> >
> 
> First hint, (as above) don't use assembly unless you have to.  And for
> putpixel, you don't have to.  The above would work just fine as
> 
>   Buf[Y*ScreenWidth+X]=Color;
> 
> Second, that multiply is expensive.  If you can replace it by a constant,
> do so.  If you can't, you may want to define your graphics buffer as follows...
> 
> typedef unsigned char pixel;
> 
> typedef struct {
>   int width,height;
>   pixel **lines;
> } GBuf;
> 
> And create a buffer as follows....
> 
> GBuf *Create_GBuf(int width, int height)
> {
>   int i;
>   GBuf *Buf=(GBuf *)calloc(1,sizeof(GBuf)+height*sizeof(pixel *)+
>                      width*height*sizeof(pixel));
>   if (Buf) {
>     Buf->width=width;
>     Buf->height=height;
>     /* Warning, confusing pointer arithmetic.  Look carefully.... */
>     Buf->lines=Buf+1;
>     Buf->lines[0]=Buf->lines+height;
>     for (i=1;i<height;i++) {
>       Buf->lines[i]=Buf->lines[i-1]+width;
>     }
>   }
>   return (Buf);
> }
> 
> Then the putpixel function becomes....
> 
> void vputpixel(int x, int y, pixel color, GBuf *Buf)
> /* This compiles to 5 instructions under SPARC */
> {
>   Buf->lines[y][x]=color;
> }
> 
> Voila, no more multiply!  (Also, the routine easily changes to support
> 16 or 32 bit color.  Just change the pixel typedef.)  (And it's portable!)
> 
> Third hint.  You are playing around with segment registers.  Don't, unless
> it's absolutely necessary.  And if you do need to, load the register from
> a dpmi or go32 variable like _go32_dos_ds or my_ds.
> 
> Hope this helps.
> 
> Eric
> --
> Eric Korpela                        |  An object at rest can never be
> korpela AT ssl DOT berkeley DOT edu            |  stopped.
> <a href="http://www.cs.indiana.edu/finger/mofo.ssl.berkeley.edu/korpela/w">
> Click here for more info.</a>

You're right! The writers did this to make money and didn't fully
optimize their code. Take, for example, the vputpixel() function. A much
faster way to do this would be through shifting with >> or <<. E-mail me
if anyone wants the code for a FAST one.

Dan

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019