I would like to ask some help form You! I have a project with a lot of C source. Most of them compiled with gcc, but some compiled with Intel compiler. This later codes have a lot of inline asm codes in Microsoft's MASM
format. I would like to compile the whole project with gcc and modify as few code as I can. So I wrote a perl script which converts the intel format inline asm to GAS format. (BTW: I compile to 32 bit on a 64 bit Linux machine).
My problem that I have to specify for gcc that in the inline asm("...")
which C variables are passed to the code adding the :: [var1] "m" var1, [var2] "m" var2, ...
line at the end.
Is it a way to avoid this explicit specification?
My tryings:
The dummy test C code is simply replaces 4 characters the destination char array with the elements of the source char array (I know this is not the best way to do it. It is just a stupid example).
In the original function there is no explicit specification, but it can be compiled with Intel compiler (shame on me, but I did not test this, but it should work with Intel compiler as I made it based on the real code). LOOP
label is used a lot of times, even in the same C source file.
#include <stdio.h>
void cp(char *pSrc, char *pDst) {
__asm
{
mov esi, pSrc
mov edi, pDst
mov edx, 4
LOOP:
mov al, [esi]
mov [edi], al
inc esi
inc edi
dec edx
jnz LOOP
};
}
int main() {
char src[] = "abcd";
char dst[] = "ABCD";
cp(src, dst);
printf("SRC: '%s', DST: '%s'\n", src, dst);
return 0;
}
Result is: SRC: 'abcd', DST: 'abcd'
The working converted cp
code is (compiled with gcc).
GAS (AT&T) format (compiled: gcc -ggdb3 -std=gnu99 -m32 -o asm asm.c
)
void cp(char *pSrc, char *pDst) {
asm(
"mov %[pSrc], %%esi\n\t"
"mov %[pDst], %%edi\n\t"
"mov $4, %%edx\n\t"
"LOOP%=:\n\t"
"mov (%%esi), %%al\n\t"
"mov %%al, (%%edi)\n\t"
"inc %%esi\n\t"
"inc %%edi\n\t"
"dec %%edx\n\t"
"jnz LOOP%=\n\t"
: [pDst] "=m" (pDst)
: [pSrc] "m" (pSrc)
: "esi", "edi", "edx", "al"
);
}
Intel format (compiled: gcc -ggdb3 -std=gnu99 -m32 -masm=intel -o asm asm.c
)
void cp(char *pSrc, char *pDst) {
asm(".intel_syntax noprefix\n\t");
asm(
"mov esi, %[pSrc]\n\t"
"mov edi, %[pDst]\n\t"
"mov edx, 4\n\t"
"LOOP%=:\n\t"
"mov al, [esi]\n\t"
"mov [edi], al\n\t"
"inc esi\n\t"
"inc edi\n\t"
"dec edx\n\t"
"jnz LOOP%=\n\t"
: [pDst] "=m" (pDst)
: [pSrc] "m" (pSrc)
: "esi", "edi", "edx", "al"
);
asm(".intel_syntax prefix");
}
Both codes are working, but it needs some code modification (inserting the '%' characters, collecting the variables, modifying the jump labels and jump
functions).
I also tried this version:
void cp(char *pSrc, char *pDst) {
asm(".intel_syntax noprefix\n\t");
asm(
"mov esi, pSrc\n\t"
"mov edi, pDst\n\t"
"mov edx, 4\n\t"
"LOOP:\n\t"
"mov al, [esi]\n\t"
"mov [edi], al\n\t"
"inc esi\n\t"
"inc edi\n\t"
"dec edx\n\t"
"jnz LOOP\n\t"
);
asm(".intel_syntax prefix");
}
But it drops
gcc -ggdb3 -std=gnu99 -masm=intel -m32 -o ./asm.exe ./asm.c
/tmp/cc2F9i0u.o: In function `cp':
/home/TAG_VR_20130311/vr/vr/slicecodec/src/./asm.c:41: undefined reference to `pSrc'
/home/TAG_VR_20130311/vr/vr/slicecodec/src/./asm.c:41: undefined reference to `pDst'
collect2: ld returned 1 exit status
Is there a way to avoid the definition of the input arguments and avoid the modifications of local labels?
ADDITION
I tried to use global variable. For this g
constrain has to be used instead of m
.
char pGlob[] = "qwer";
void cp(char *pDst) {
asm(".intel_syntax noprefix\n\t"
"mov esi, %[pGlob]\n\t"
"mov edi, %[pDst]\n\t"
"mov edx, 4\n\t"
"LOOP%=:\n\t"
"mov al, [esi]\n\t"
"mov [edi], al\n\t"
"inc esi\n\t"
"inc edi\n\t"
"dec edx\n\t"
"jnz LOOP%=\n\t"
".intel_syntax prefix" : [pDst] "=m" (pDst) : [pGlob] "g" (pGlob)
: "esi", "edi", "edx", "al");
}
ADDITION#2
I tried
"lea esi, pGlob\n\t" // OK
"lea esi, %[_pGlob]\n\t" // BAD
//"lea esi, pGlob_not_defined\n\t" // BAD
//gcc failed with: undefined reference to `pGlob_not_defined'
compiled to
lea esi, pGlob
lea esi, OFFSET FLAT:pGlob // BAD
//compilation fails with: Error: suffix or operands invalid for `lea'
It seems that only function local variables has to be defined. Global variable may be added to the trailer, but not really necessary. Both are working:
"mov esi, pGlob\n\t" // OK
"mov esi, %[_pGlob]\n\t" // OK
compiled to
mov esi, OFFSET FLAT:pGlob
mov esi, OFFSET FLAT:pGlob
I defined a function local variable. It has to be defined in the constraint part:
void cp(char *pDst) {
char pLoc[] = "yxcv";
asm(".intel_syntax noprefix\n\t"
...
//"mov esi, pLoc\n\t" // BAD
"mov esi, %[_pLoc]\n\t" // OK, 'm' BAD
...
".intel_syntax prefix" : [_pDst] "=m" (pDst) : [_pLoc] "g" (pLoc)
: "esi", "edi", "edx", "al");
Unfortunately it should be determined what are the global and what are the local variables. It is not easy as the asm code can be defined in C
macros and even the surrounding function is not definite. I think only the precompiler has enough information to this. Maybe the code has to be precompiled with gcc -E ...
.
I realized that not defining the output in the constraint part, some code can be eliminated by the optimizer.
TIA!