将asm插入c时mul的操作数不匹配
我试图在C代码中插入一个程序集。然而,当我尝试将其中的两个寄存器相乘时,会出现一个错误,即操作数不匹配。我尝试了将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
“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;
}
此外,我也意识到,通常情况下,你会按照评论中显示的方式返回变量,但它不起作用,所以根据我教授的建议,我用这种方式编写程序
谢谢大家的帮助!当我试图避免为他们“做家庭作业”时,你已经解决了这个问题,考虑到已经一个多星期了,你可能已经交了
所以,看看你的最终解决方案,有一些事情你可能会想做不同的事情。没有特别的顺序:
mov$0,%%rbx
确实会在rbx中归零,但这并不是将寄存器归零的最有效方法。使用xor%%rbx,%%rbx
在显微镜下速度更快,生成的可执行代码更小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;
}