Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.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
将asm插入c时mul的操作数不匹配_C_Assembly_X86 - Fatal编程技术网

将asm插入c时mul的操作数不匹配

将asm插入c时mul的操作数不匹配,c,assembly,x86,C,Assembly,X86,我试图在C代码中插入一个程序集。然而,当我尝试将其中的两个寄存器相乘时,会出现一个错误,即操作数不匹配。我尝试了“mul%%bl,%%cl\n”(加倍%%,因为它是C代码)。根据我过去使用asm的经验,我认为这应该有效。我还尝试了“mul%%cl\n”(首先将bl移动到al),但在这种情况下,我从链接器中得到了大量错误 zad3:(.rodata+0x4): multiple definition of `len' /tmp/ccJxYyIp.o:(.rodata+0x0): first def

我试图在C代码中插入一个程序集。然而,当我尝试将其中的两个寄存器相乘时,会出现一个错误,即操作数不匹配。我尝试了
“mul%%bl,%%cl\n”
(加倍%%,因为它是C代码)。根据我过去使用asm的经验,我认为这应该有效。我还尝试了
“mul%%cl\n”
(首先将bl移动到al),但在这种情况下,我从链接器中得到了大量错误

zad3:(.rodata+0x4): multiple definition of `len'
/tmp/ccJxYyIp.o:(.rodata+0x0): first defined here
zad3: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o:(.fini+0x0): first defined here
zad3: In function `data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.data+0x0): first defined here
zad3: In function `data_start':
(.data+0x8): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-linux-gnu/5/crtbegin.o:(.data+0x0): first defined here
zad3:(.rodata+0x0): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o:(.rodata.cst4+0x0): first defined here
zad3: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: (.text+0x0): first defined here
zad3: In function `data_start':
(.data+0x10): multiple definition of `str'
/tmp/ccJxYyIp.o:(.data+0x0): first defined here
/usr/bin/ld: Warning: size of symbol `str' changed from 4 in   /tmp/ccJxYyIp.o to 9 in zad3
zad3: In function `main':
(.text+0xf6): multiple definition of `main'
/tmp/ccJxYyIp.o:zad3.c:(.text+0x0): first defined here
zad3: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crti.o:(.init+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/5/crtend.o:(.tm_clone_table+0x0): multiple definition of `__TMC_END__'
zad3:(.data+0x20): first defined here
/usr/bin/ld: error in zad3(.eh_frame); no .eh_frame_hdr table will be created.
collect2: error: ld returned 1 exit status
据我所知,它告诉我我定义了len和其他几个变量好几次,但我看不到这个多重定义。 我的程序的目标是获取一个数字串并计算它们的和,但以2为基数。假设字符串是293,那么我想计算
2*2^2+9*2^1+3*2^0
代码:

#包括
字符str[]=“543”;
常数int len=3;
内部主(空)
{
asm(
mov$0,%%rbx\n
mov$1,%%rcx\n
“potega:\n”
shl$1,%%cl\n
“inc%%rbx\n”
“cmp透镜,%%ebx\n”
“jl potega\n”
mov$0,%%rbx\n
“佩特拉:\n”
mov(%0,%%rbx,1),%%al\n
“子$48,%%al\n”
“mul%%al,%%cl\n”
shr$1,%%cl\n
添加$48、%%al\n
“mov%%al,(%0,%%rbx,1)\n”
“inc%%rbx\n”
“cmp透镜,%%ebx\n”
“jl petla\n”
:“r”(&str)
:%rax、%rbx、%rcx
);
printf(“Wynik:%s\n”,str);
返回0;
}

正如有人指出的——是的,这是一个学生练习。 说到我原来的问题,当我删除行
add$48时,%%al\n“
它起了作用。我还切换到
mul%%cl

当谈到其余的问题时,你指出,我和我的教授谈过,她稍微改变了主意(或者我第一次把假设搞错了——不管你觉得什么更可能),现在她想让我从内联函数返回一个参数,并说intiger类型很好。这导致我编写了这样一段代码(这实际上是我想要的)

例如:“543”->5*(2^2)+4*(2^1)+3*(2^0)=31

#包括
字符str[]=“543”;
常数int len=3;
int len1=2;
int结果;
int main(){
asm(
mov$0,%%rbx\n
mov$1,%%rcx\n
mov$0,%%rdx\n
“potega:\n”
“inc%%rbx\n”
shl$1,%%cl\n
“cmp len1,%%ebx\n”
“jl potega\n”
mov$0,%%rbx\n
“佩特拉:\n”
mov(%0,%%rbx,1),%%al\n
“子$48,%%al\n”
“mul%%cl\n”
shr$1,%%cl\n
添加%%al,%%dl\n
“inc%%rbx\n”
“cmp透镜,%%ebx\n”
“jl petla\n”
movl%%edx,结果\n
:/“=r”(结果)
:“r”(&str)、“r”(&result)
:%rax、%rbx、%rcx、%rdx
);
printf(“Wynik:%d\n”,结果);
返回0;
}
此外,我也意识到,通常情况下,你会按照评论中显示的方式返回变量,但它不起作用,所以根据我教授的建议,我用这种方式编写程序

谢谢大家的帮助!

当我试图避免为他们“做家庭作业”时,你已经解决了这个问题,考虑到已经一个多星期了,你可能已经交了

所以,看看你的最终解决方案,有一些事情你可能会想做不同的事情。没有特别的顺序:

  • 注释。虽然所有代码都需要注释,但asm确实需要注释。正如您将从我的解决方案(下面)中看到的那样,在代码旁边添加注释确实有助于澄清代码的作用。这似乎是一个家庭作业项目,几乎不需要它们。但自从你在这里发布此代码以来,已有89人尝试阅读此代码。注释会让我们所有人都更容易阅读此代码。更不用说,当你来到bac时,它会让你的“未来自我”生活更轻松努夫说:“从现在起,我将在k个月内努力维护它。”

  • 归零寄存器。虽然
    mov$0,%%rbx
    确实会在rbx中归零,但这并不是将寄存器归零的最有效方法。使用
    xor%%rbx,%%rbx
    在显微镜下速度更快,生成的可执行代码更小

  • potega。在没有任何评论的情况下,我花了一点时间来整理您在第一个循环中所做的工作。您正在使用rbx跟踪您已处理的字符数,而cl会为每个字符向左移动一个。这里有一些想法:

    3a.我要做的第一件事是将
    shl$1、%%cl
    移出循环。不要同时进行递增和移位,只需计算字符数,然后进行适当大小的单个移位。这(稍微)复杂,因为如果要按可变量移位,则必须在cl中指定移位量(即
    shl%%cl,%%rbx
    )。为什么是cl?谁知道呢?这就是
    shl
    的工作原理。因此,您希望在cl而不是rbx中进行计数

    3b.关于此循环的第二件事与
    len1
    有关。既然您已经知道大小(它在
    len1
    中),为什么您甚至需要一个循环?也许更明智的方法是:

    3c.C中的字符串以空字符(也称为0)结尾。如果要查找字符串的长度,通常需要遍历字符串,直到找到为止。这样就不需要使用
    len1

    3d.您的代码假定输入字符串有效。如果通过“abc”或“abc”,会发生什么情况“?验证参数既无聊又耗时,而且会使程序变大、运行变慢。另一方面,当出现意外错误时,它会带来巨大的回报。至少你应该指定你对输入的假设。”

    3e.使用全局变量通常不是一个好主意。您会遇到命名冲突(两个文件都使用名称len1),在几个不同的文件中编写代码,所有这些文件都会更改值(使bug难以追踪)它可以使您的程序比需要的更大。有时全局变量很有用,但这似乎不是其中之一。这里的唯一目的似乎是允许从asm中访问这些变量,还有其他方法可以做到这一点

    3f.您使用
    %0
    引用
    
    
    #include <stdio.h>
    char str[] = "543";
    const int len = 3;
    
    int main(void)
    {
    asm(
    "mov $0, %%rbx \n"
    "mov $1, %%rcx \n"
    
    "potega: \n" 
    "shl $1, %%cl \n" 
    "inc %%rbx \n"
    "cmp len, %%ebx \n"
    "jl potega \n"
    
    
    "mov $0, %%rbx \n" 
    
    "petla: \n" 
    "mov (%0, %%rbx, 1), %%al \n" 
    
    "sub $48, %%al \n"
    
    "mul %%al, %%cl \n"  
    "shr $1, %%cl \n"    
    
    "add $48, %%al \n"
    
    "mov %%al, (%0, %%rbx, 1) \n" 
    
    "inc %%rbx \n"  
    "cmp len, %%ebx \n" 
    "jl petla \n" 
    
    :"r"(&str)
    :"%rax", "%rbx", "%rcx" 
    );
    printf("Wynik: %s\n", str);
    return 0;
    }
    
    #include <stdio.h>
    char str[] = "543";
    const int len = 3;
    int len1 = 2;
    int result;
    
    int main(){
    asm(
        "mov $0, %%rbx\n"
        "mov $1, %%rcx\n"
        "mov $0, %%rdx\n"
    
        "potega: \n"
        "inc %%rbx\n"
        "shl $1, %%cl\n"
        "cmp len1, %%ebx \n"
        "jl potega\n"
    
        "mov $0, %%rbx\n"
    
        "petla:\n"
        "mov (%0, %%rbx, 1), %%al\n"
        "sub $48, %%al\n"
        "mul %%cl\n"
        "shr $1, %%cl\n"
        "add %%al, %%dl\n"
        "inc %%rbx\n"
        "cmp len, %%ebx\n"
        "jl petla\n"
    
        "movl %%edx, result\n"
    
        ://"=r"(result)
    
        :"r"(&str), "r"(&result)
    
        :"%rax", "%rbx", "%rcx", "%rdx"
    
    );
    printf("Wynik: %d\n", result);
    return 0;
    }
    
         "xor %%rcx, %%rcx\n"             // Zero the strlen count
    
      // Count how many characters in string
      "potega%=: \n\t"
    
         "mov (%[pstr], %%rcx), %%bl\n\t" // Read the next char
    
         "test %%bl, %%bl \n\t"           // Check for 0 at end of string
         "jz kont%= \n\t"
    
         "cmp $'0', %%bl\n\t"             // Ensure digit is 0-9
         "jl gotowe%=\n\t"
         "cmp $'9', %%bl\n\t"
         "jg gotowe%=\n\t"
    
         "inc %%rcx \n\t"                 // Increment index/len
         "jmp potega%= \n"
    
      "kont%=:\n\t"
    
      // rcx = the number of character in the string excluding null
    
      "petla%=:\n\t"
    
         "mov (%[pstr], %%rcx, 1), %%al\n\t" // read the next char
         "sub $'0', %%al\n\t"                // convert char to value
         "mul %%bl\n\t"                      // mul bl * al -> ax
         "add %%ax, %[res]\n\t"              // Accumulate result
         "inc %%rcx\n\t"                     // move to next char
         "shr $1, %%rbx\n\t"                 // decrease our exponent
         "jnz petla%=\n"                     // Has our exponent gone to 0?
    
      "gotowe%=:"
    
      :[res] "=r"(result)
      :[pstr] "r"(str), "0"(0)
    
      :"%rax", "%rbx", "%rcx", "cc"
    
    /*
    
    my_file.c - The goal of this program is to take a string of numbers and 
    count sum of them but using 2 as a base.
    
    example: "543" -> 5*(2^2)+4*(2^1)+3*(2^0)=31
    
    */
    
    #include <stdio.h>
    
    void TestOne(const char *str)
    {
       short result;
    
       // Code assumes str is not NULL.  Strings with non-digits and zero
       // length strings return 0.
    
       asm(
             "xor %%rcx, %%rcx\n"             // Zero the strlen count
    
          // Count how many characters in string
          "potega%=: \n\t"
    
             "mov (%[pstr], %%rcx), %%bl\n\t" // Read the next char
    
             "test %%bl, %%bl \n\t"           // Check for 0 at end of string
             "jz kont%= \n\t"
    
             "cmp $'0', %%bl\n\t"             // Ensure digit is 0-9
             "jl gotowe%=\n\t"
             "cmp $'9', %%bl\n\t"
             "jg gotowe%=\n\t"
    
             "inc %%rcx \n\t"                 // Increment index/len
             "jmp potega%= \n"
    
          "kont%=:\n\t"
    
          // rcx = the number of character in the string excluding null
    
             "dec %%rcx \n\t"       // We want to shift rbx 1 less than pstr length
             "jl gotowe%=\n\t"      // Check for zero length string
    
             "mov $1, %%rbx\n\t"    // Set exponent for first digit
             "shl %%cl, %%rbx\n\t"
    
             "xor %%rcx, %%rcx\n"   // Reset string index
    
          "petla%=:\n\t"
    
             "mov (%[pstr], %%rcx, 1), %%al\n\t" // read the next char
             "sub $'0', %%al\n\t"                // convert char to value
             "mul %%bl\n\t"                      // mul bl * al -> ax
             "add %%ax, %[res]\n\t"              // Accumulate result
             "inc %%rcx\n\t"                     // move to next char
             "shr $1, %%rbx\n\t"                 // decrease our exponent
             "jnz petla%=\n"                     // Has our exponent gone to 0?
    
          "gotowe%=:"
    
          :[res] "=r"(result)
          :[pstr] "r"(str), "0"(0)
    
          :"%rax", "%rbx", "%rcx", "cc"
       );
    
       printf("Wynik: \"%s\" = %d\n", str, result);
    }
    
    int main(){
    
       TestOne("x");
       TestOne("");
       TestOne("5");
       TestOne("54");
       TestOne("543");
       TestOne("5432");
    
       return 0;
    }