Mail Archives: djgpp/1997/11/01/13:22:35
At 02:54 10/31/1997 EST, VANGEL AT vmredipn DOT ipn DOT mx wrote:
>Hi ...
>I run the fellow program:
>
>/*******************************************************************/
>
>#include <stdio.h>
>#include <stdlib.h>
>
>void square( unsigned long *a, unsigned long *b )
>{
> /* This function squares a 48-bit number "a" into a
> 96 bit number "b", stored in binary and in little-
> endian order. */
>
> __asm__ ("
> movl (%0), %%eax \n
> mull %%eax \n
> movl %%eax, (%1) \n
> movl 4(%0), %%eax \n
> mull %%eax \n
> movl %%eax, 8(%1) \n
> movl %%edx, 4(%1) \n
> movl 4(%0), %%eax \n
> mull (%0) \n
> addl %%eax, %%eax \n
> adcl %%edx, %%edx \n
> addl %%eax, 4(%1) \n
> adcl %%edx, (%1) \n"
> :
> : "g"(a), "g"(b)
> : "%eax", "%edx", "memory");
>}
>
>/*---------------------------------------------------------------------*/
>
>int main(int argc,char *argv){
> unsigned long b3,a2;
>
> a0=atol(argv1);
> a1=atol(argv2);
>
> square(a,b);
>
> printf("%.8x %.8x %.8x\n\n", b0, b1, b2);
> return 0;
>}
>----------------------------------------------------------------------------
>
>And I get the fellow errors :
>
>C:\TC\ASMG>gcc -Wall pp1.c -o pp11.exe
>pp1.c: In function `main':
>pp1.c:42: warning: unsigned int format, long unsigned int arg (arg 2)
>pp1.c:42: warning: unsigned int format, long unsigned int arg (arg 3)
>pp1.c:42: warning: unsigned int format, long unsigned int arg (arg 4)
The reason for that is your printf() format arguments. It's not really a
problem on DJGPP, where `unsigned int' and `long unsigned int' are the same,
but you should probably change it to "%.8lx", if I remember correctly.
>C:\djgpp\tmp\cccaaaaa: Assembler messages:
>C:\djgpp\tmp\cccaaaaa:12: Error: Missing ')' assumed
>C:\djgpp\tmp\cccaaaaa:12: Error: Ignoring junk '(%ebp))' after expression
[and so on]
Okay. The problem here is that you have pointer variables set up as a "g"
operand. Since they're already on the stack, the compiler substitutes in
their address, like `8(%ebp)'. It doesn't know that you are trying to use it
indirectly, so the assembler output looks like:
movl (8(%ebp)), eax
which is clearly wrong. You are trying to do double indirection with one
instruction, which the processor can't do.
So how do you fix it? Offhand, I can see two possibilities.
1. Have the compiler load the arguments `a' and `b' into registers. You
could do this by specifying an "r" constraint, but then it might use a
register that you use for something else, causing problems. You could
explicitly put them in registers you aren't using, like ESI and EDI, by
using the "S" and "D" constraints.
2. Be aware that a pointer may be used, and use one `mov' to get the pointer
into a register, then use that as your variable. I.E.:
movl %0, %%esi # or some other register you can spare
movl (%%esi), %%eax
Don't forget to add any other registers you use to the "clobber" list.
Nate Eldredge
eldredge AT ap DOT net
- Raw text -