From: "Salvador Tropea,ICE" 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.