From: korpela AT islay DOT ssl DOT berkeley DOT edu (Eric J. Korpela) Newsgroups: comp.os.msdos.djgpp Subject: Re: Intel ASM to AT&T ASM question Date: 6 Jan 1997 18:10:03 GMT Organization: Cal Berkeley-- Space Sciences Lab Lines: 124 Message-ID: <5arf5r$lqn@agate.berkeley.edu> References: <01b9b9ca$9cccd040$aaf15ecf AT platko DOT ix DOT netcom DOT com> NNTP-Posting-Host: islay.ssl.berkeley.edu To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp 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;ilines[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. Click here for more info.