Mail Archives: djgpp/1998/12/18/19:13:41
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
- Raw text -