delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/05/08/16:06:26

From: "Salvador Tropea,ICE" <salvador AT inti DOT edu DOT ar>
To: djgpp AT delorie DOT com
Subject: Problems with inline asm of GCC 2.7.2
Date: Wed, 8 May 1996 14:33:59 +0300 (GMT)
Message-ID: <9605081434.aa25285@ailin.inti.edu.ar>

Hi everybody:

In Brief:

1) Problems with JCXZ.
2) C Extensions to inline asm not supported under C++!!!???
3) GCC is idiot or is a nest of bugs?
4) Hey, ES,GS and FS are registers, but GCC don't know this.
5) Conclutions.

Descriptions:

1) The following code works OK:

int countLines( void *buf, uint32 count )
{
register long Ret asm ("%eax");

asm ("pushl %edx");
asm ("pushl %ecx");
asm ("pushl %edi");
asm ("pushw %es");

asm ("pushw %ds");
asm ("popw  %es");

asm ("movl  %k0,%%ecx": /* no out */ : "m" (count) );
asm ("movl  %k0,%%edi": /* no out */ : "m" (buf) );
asm ("xorl  %edx,%edx");

asm ("movb  $0xD,%al");

asm ("cld");

asm ("countLines__1:");
asm ("orl %ecx,%ecx");        // *
asm ("jz  countLines__2");    // *
asm ("RepNe");
asm ("Scasb");
asm ("Jne   countLines__2");
asm ("Inc   %edx");
asm ("Jmp   countLines__1");
asm ("countLines__2:");

asm ("movl %edx,%eax");

asm ("popw  %es");
asm ("popl %edi");
asm ("popl %ecx");
asm ("popl %edx");
return Ret;
}

  But if i replace the lines with // * for:

asm ("Jcxz  countLines__2");

  The program crash and the trace of the stack don't say nothing about this
routine.
  I'm crazy? I'm dreaming? Any body saw some thing like this?

2) In the GCC.INF manual under C Extensions says that:

asm ("Scasb":::"%ecx","%edi");

 Tells to GCC that this line touchs the ECX and EDI registers, but the same
syntax under C++ reports:

inasm.cpp: In function `int countLines(void *, unsigned int)':
inasm.cpp:25: parse error before `::'
inasm.cpp:26: parse error before `::'
inasm.cpp:28: parse error before `::'

 For C i use: gcc -S -O2 inasm.c
 For C++    : gcc -S -O2 inasm.cpp

 Is that a bug? There are any reason to turn off this good extention under
C++?

3) Another extention is:

register int a asm ("%edx");

 And tells to GCC that "a" is the EDX register (cool :). But ....

 The following code:

int pepe(void)
{
 register int a asm ("%edx");

 a=0;
 asm ("Incl %%edx":::"%edx");

 return a;
}

 Generates:

        .file   "pp.c"
gcc2_compiled.:
___gnu_compiled_c:
.text
        .align 2
.globl _pepe
_pepe:
        pushl %ebp
        movl %esp,%ebp
        xorl %edx,%edx
/APP
        Incl %edx
/NO_APP
        movl %edx,%eax
        jmp L1
        .align 2,0x90
L1:
        leave
        ret

 If i use gcc -S -O0 pp.c, and that's OK but i don't like the stupid jmp L1,
and i need that the rest of the code in the file will be optimized, then if
i try gcc -S -O2 pp.c surprise!!!, i get:

        .file   "pp.c"
gcc2_compiled.:
___gnu_compiled_c:
.text
        .align 2
.globl _pepe
_pepe:
        pushl %ebp
        movl %esp,%ebp
/APP
        Incl %edx
/NO_APP
        movl %edx,%eax
        leave
        ret

 Hey!!!!, i say a=0 !!!!, i was specting some thing like:

.globl _pepe
_pepe:
        pushl %ebp
        movl %esp,%ebp
        xorl %edx,%edx
        Incl %edx
        movl %edx,%eax
        leave
        ret

Or better:

.globl _pepe
_pepe:
        pushl %ebp
        movl %esp,%ebp
        movl $1,%eax
        leave
        ret

 This is only a little example, the real problem is with the routine of the
point 1). But if GCC can't handle this 4 lines routine .... :( ={

4) If i put:

asm ("Movw $0,%%es":::"%es"); (I don't want to do that is only an example ;)

  I get:

pp3.c: In function `pepe':
pp3.c:8: unknown register name `%es' in `asm'

  I give up man ...

Note: When i say GCC in general i'm talking about CC1 and CC1PLUS, of course
AS knows that ES,GS and FS are registers.

5) From my point of view there isn't any way to get a good inline asm code
with GCC, the example is the routine of the point 1), in this routine i don't
guess any thing (a little lie, i guess that cld don't go to destroy the
rest of the program).
   Then what things can i guess? Are true the following?:

* ES=DS, at any time.
* GS and FS can be used for any function but this function *must* restore the
original value before return (of course i exclude the farptr macros).
* EDI,ESI and EBX must be restored.
* ECX,EDX and EAX can be used.
* EAX is the return value.

  guess over guess:

* If i alter ES, and don't restore the value, the program crash.
* I can use GS and FS like globals variables in all my application (this
excludes: functions called from any library, interrupt routines and routines
for libraries).

  I arrive to this conclutions compiling:

int pepe(void)
{
 asm ("Movl $0,%%ebx":::"%ebx");
 asm ("Movl $0,%%ecx":::"%ecx");
 asm ("Movl $0,%%edx":::"%edx");
 asm ("Movl $0,%%edi":::"%edi");
 asm ("Movl $0,%%esi":::"%esi");
 asm ("Movw $0,%%es":::"%es");
 return 0;
}

  And geting (with -O0):

.globl _pepe
_pepe:
        pushl %ebp
        movl %esp,%ebp
        pushl %edi
        pushl %esi
        pushl %ebx
/APP
        Movl $0,%ebx
        Movl $0,%ecx
        Movl $0,%edx
        Movl $0,%edi
        Movl $0,%esi
        Movw $0,%es
/NO_APP
        xorl %eax,%eax
        jmp L1
        .align 2,0x90
L1:
        leal -12(%ebp),%esp
        popl %ebx
        popl %esi
        popl %edi
        leave
        ret

  Have a nice day, is you can ...

SET.


- Raw text -


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