Mail Archives: djgpp/1996/05/08/16:06:26
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 -