如何将变量传递给Intel格式内联汇编code用gcc编译 [英] How to pass variables to intel format inline asm code compiled with gcc

查看:146
本文介绍了如何将变量传递给Intel格式内联汇编code用gcc编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想问一些帮助的形式你!我有很多C源代码的项目。他们大多用gcc编译,但一些与英特尔编译器编译。这以后codeS有很多内联汇编codeS的微软 MASM 格式。我想编译使用gcc整个项目并修改尽可能少code,我可以。所以我写了,它把Intel格式内联汇编到GAS格式的perl脚本。 (BTW:我编译为32位64位的Linux机器上)

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).

我的问题,我必须指定海湾合作委员会,在联 ASM(...)其中C变量传递到code加入在结束 :: [VAR1]MVAR1,[VAR2]MVAR2,... 行。

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?

我tryings:

假人测试C code是只是替换4个字符与字符源数组的元素目标字符数组(我知道这是不是做的最好的方法。这仅仅是一个愚蠢的例子)。

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).

在原有的功能没有明确的规范,但它可以与英特尔的编译器(可耻的是我编的,但我没有测试这一点,但它应该与英特尔的编译器根据实际$ C工作,因为我做到了$ C)。 LOOP 标签使用了很多次,即使在同一个C源文件。

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;
}

的结果是: SRC:ABCD,DST:ABCD

工作转换 CP code为(用gcc编译)。

The working converted cp code is (compiled with gcc).

GAS(AT&amp; T公司)格式(编译: GCC -ggdb3 -std = gnu99 -m32 -o ASM asm.c

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"
    );
}

英特尔格式(编译: GCC -ggdb3 -std = gnu99 -m32 -masm =英特尔-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");
}

这两个codeS的工作,但它需要一些code修改(插入'%'字符,收集的变量,修改跳标签和函数)。

我也试过这个版本:

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");
}

但它丢弃

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?

加成

我试着使用全局变量。对于本先按g 约束已被用来代替 M

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");
}

加成#2

我试过

            "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'

编译

            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

编译

             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");

不幸的是,应该确定什么是全球性,什么是局部变量。这是不容易的ASM code可以在 C 宏连周围的功能不明确的定义。我想只有precompiler有足够的信息来此。也许code必须与pcompiled $ P $ gcc的-E ...

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 ....

我意识到,如果不定义在约束部分的输出,一些code可以通过优化淘汰。

I realized that not defining the output in the constraint part, some code can be eliminated by the optimizer.

TIA!

推荐答案

是的,你确实需要明确指定寄存器。 GCC不会为你做的。而且你不能(一般)把C变量名ASM字符串中。

Yes, you do need to specify the registers explicitly. GCC will not do that for you. And you can't (generally) put C variable names inside the ASM string.

您最后code座看起来非常好,对我来说,但是在GCC你不需要选择哪个注册使用你自己。你也应该使用挥发性关键字prevent编译想着code没有做任何事情,因为它没有输出。

Your final code block looks perfectly good, to me, but in GCC you don't need to choose which registers to use yourself. You should also use the volatile keyword to prevent the compiler thinking the code doesn't do anything given that it has no outputs.

试试这个:

char pGlob[] = "qwer";
void cp(char *pDst) {
    asm volatile (".intel_syntax noprefix\n\t"
            "mov edx, 4\n\t"
    "LOOP%=:\n\t"
            "mov al, [%[pGlob]]\n\t"
            "mov [%[pDst]], al\n\t"
            "inc %[pGlob]\n\t"
            "inc %[pDst]\n\t"
            "dec edx\n\t"
            "jnz LOOP%=\n\t"
            ".intel_syntax prefix" :: [pGlob] "g" (pGlob), [pDst] "g" (pDst) : "edx");
}

此的方式与加载变量和选择寄存器你(从而消除了从一个寄存器一个毫无意义的复制到另一个)编译器的交易。理想情况下,你想也消除了明确使用 EDX ,但这里是不是真的有必要。

This way the compiler deals with loading the variables and chooses the registers for you (thereby eliminating a pointless copy from one register to another). Ideally you'd also eliminate the explicit use of edx, but it's not really necessary here.

当然,在这个愚蠢的例子,我只想重新code在C整个事情,让编译器完成其工作。

Of course, in this silly example I would just recode the whole thing in C and let the compiler do its job.

这篇关于如何将变量传递给Intel格式内联汇编code用gcc编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆