www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1998/12/18/19:13:41

Sender: nate AT cartsys DOT com
Message-ID: <367AEC65.4A84AC7B@cartsys.com>
Date: Fri, 18 Dec 1998 15:59:33 -0800
From: Nate Eldredge <nate AT cartsys DOT com>
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>
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

- Raw text -


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