Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将变量传递到使用gcc编译的英特尔格式内联asm代码_C_Gcc_Assembly - Fatal编程技术网

如何将变量传递到使用gcc编译的英特尔格式内联asm代码

如何将变量传递到使用gcc编译的英特尔格式内联asm代码,c,gcc,assembly,C,Gcc,Assembly,我想请你帮忙!我有一个有很多C源代码的项目。其中大多数是用gcc编译的,但有些是用英特尔编译器编译的。后面的代码有很多微软MASM格式的内联asm代码。我想用gcc编译整个项目,并修改尽可能少的代码。因此,我编写了一个perl脚本,将intel格式的内联asm转换为GAS格式。(顺便说一句:我在64位Linux机器上编译为32位) 我的问题是,我必须为gcc指定,在内联asm(“…”中,哪些C变量被传递给代码,并在末尾添加::[var1]“m”var1、[var2]“m”var2、行 这是避免这

我想请你帮忙!我有一个有很多C源代码的项目。其中大多数是用gcc编译的,但有些是用英特尔编译器编译的。后面的代码有很多微软
MASM
格式的内联asm代码。我想用gcc编译整个项目,并修改尽可能少的代码。因此,我编写了一个perl脚本,将intel格式的内联asm转换为GAS格式。(顺便说一句:我在64位Linux机器上编译为32位)

我的问题是,我必须为gcc指定,在内联
asm(“…”
中,哪些C变量被传递给代码,并在末尾添加
::[var1]“m”var1、[var2]“m”var2、

这是避免这种显式规范的一种方法吗

我的努力:

虚拟测试C代码只是用源字符数组的元素替换目标字符数组中的4个字符(我知道这不是最好的方法,这只是一个愚蠢的例子)

在原始函数中没有明确的规范,但它可以使用英特尔编译器进行编译(我很遗憾,但我没有测试它,但它应该可以使用英特尔编译器,因为我是基于真实代码制作的)<代码>循环标签被多次使用,即使在同一个C源文件中也是如此

#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;
}
英特尔格式(编译:
gcc-ggdb3-std=gnu99-m32-masm=Intel-o asm.c

这两个代码都正常工作,但它需要一些代码修改(插入“%”字符、收集变量、修改跳转标签和
jump
函数)

我也试过这个版本:

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
有没有办法避免输入参数的定义和本地标签的修改

添加

我尝试使用全局变量。为此,必须使用
g
约束,而不是
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'
             mov esi, OFFSET FLAT:pGlob
             mov esi, OFFSET FLAT:pGlob
似乎只需要定义函数局部变量。全局变量可以添加到拖车中,但实际上不需要。两者都在发挥作用:

            "mov esi, pGlob\n\t" // OK
            "mov esi, %[_pGlob]\n\t" // OK
编译为

            lea esi, pGlob
            lea esi, OFFSET FLAT:pGlob // BAD
            //compilation fails with: Error: suffix or operands invalid for `lea'
             mov esi, OFFSET FLAT:pGlob
             mov esi, OFFSET FLAT:pGlob
我定义了一个函数局部变量。必须在约束零件中定义:

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代码可以在
C
宏中定义,甚至周围的函数也不确定。我认为只有预编译器有足够的信息来解释这一点。可能代码必须使用
gcc-E…
进行预编译

我意识到不在约束部分定义输出,优化器可以消除一些代码


蒂亚

是的,您确实需要明确指定寄存器。GCC不会为您这样做。而且(通常)不能将C变量名放入ASM字符串中

在我看来,您的最终代码块看起来非常好,但在GCC中,您不需要自己选择使用哪个寄存器。您还应该使用
volatile
关键字来防止编译器在没有输出的情况下认为代码没有任何作用

试试这个:

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
,但在这里并不真正需要


当然,在这个愚蠢的例子中,我会用C重新编码整个过程,让编译器完成它的工作。

谢谢你的回答!问题没有解决问题,但可能没有好的解决办法。挥发性物质是一种很好的添加剂,谢谢!