Sender: nate AT cartsys DOT com Message-ID: <367AEC65.4A84AC7B@cartsys.com> Date: Fri, 18 Dec 1998 15:59:33 -0800 From: Nate Eldredge X-Mailer: Mozilla 4.08 [en] (X11; I; Linux 2.0.35 i486) MIME-Version: 1.0 To: djgpp AT delorie DOT com Subject: Re: problem with random-functions References: <36791F45 DOT 28CC128 AT gmx DOT net> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Reply-To: djgpp AT delorie DOT com Please post in plain text, not HTML. Christian Hofrichter wrote: > > I have problem with one of my funtions that usually works fine but > crashes with a general protection-fault evertime when I call the > random-function before. The strange think is, that if I use a loop and > put the random-function in it behind my function it works, but if I > try to execute it before I get this general protection-fault. My > function changes the ds-register and es-registers because it uses > "movsl" to copy memory-blocks. So could anyone tell me if the random > function changes something which causes the crash of my program ? > PS: What my function does is to try to copy an image to the vesa > framebuffer. > > > void prot_putsprite(unsigned short X1,unsigned short Y1,void *image) > { > unsigned long address; > unsigned short heigth,width,Y=0; > > > width=*(unsigned short *)image; > heigth=*(unsigned short *)((unsigned char *)image+2); > (unsigned char *)image+=4; /* update pointer so that it points to the > image-information*/ > address=Y1*infomode.BytesPerScanline+X1; > asm("cld");/*clear direction flag so that esi and edi are increased*/ > do > { > asm("pushb %ds");/*save data-segment*/ > asm("movw %0,%%es": > :"r"((unsigned short) vesa_framebuffer) > );/*selector for framebuffer*/ > asm("movl %0,%%edi" : > :"r"(address) ); /*address in framebuffer*/ > asm("movl %0,%%esi": > :"r"(image) ); /*pointer to image*/ > asm("movw %0,%%cx" : > :"r"(width) ); /*count of bytes to move*/ > asm("movw %0,%%ds": > :"r"(program-selector) ); /*same as _my_ds() */ > asm("movb %cl,%bl ");/* get the number of bytes which aren't > completely > divisible by 4*/ > asm("shr $2,%ecx ");/* calculate count of dword-movement*/ > asm("and $3,%bl "); > asm("rep\n\t" > "movsl": > : > :"%ecx","%esi","%edi"); /* move 4-bytes at one > time*/ > asm("movb %bl,%cl"); > asm("rep\n\t" > "movsb": > : > :"%ecx","%esi","%edi");/*move the bytes which > aren't completely > divisible by > 4*/ > asm("popb %ds");/*restore data-segment*/ > (unsigned char *)image+=width;/* update pointer*/ > address+=infomode.BytesPerScanline;/* update address in framebuffer*/ > Y++; > }while(Y<=heigth); > > } > > > PPS: I have written it in assembler because so I can move 4 bytes at > one time without making a conditionel jump and reloading all needed > registers if the width of the image isn't completely divisible by 4. > PPPS: Propably this discription won't help you much. There are several problems here. First, you need to combine all your assembler stuff into a single `asm'. You can't safely assume that nothing will change between two adjacent `asm's. You clobber the %es register, which is probably the cause of your crash. GCC assumes that %ds always equals %es, so it can inline `memcpy' and such. You need to save and restore it. %ds is not a byte, so `pushb'/`popb' makes no sense. I'm surprised the assembler doesn't choke. Unmatched push/pop in a single `asm' is deadly. The compiler doesn't expect the stack pointer to change unless it does it. In fact, even a matched push/pop is unsafe if you use operands between them that might be in memory ("m" or "g" constraints), and your code might ever be compiled with `-fomit-frame-pointer', a common optimization option. It's probably safer to save and restore segment regs by moving to a scratch register, or to some temporary variable. There might be other bugs, but you'll have to fix these first. -- Nate Eldredge nate AT cartsys DOT com