该代码存在一些问题 - 在我的系统中,它甚至没有运行编译器/汇编程序。主要的问题是,你需要$
前缀的所有文字,否则汇编器总是假设一个内存访问:
asm("movl 8,%ecx"); // tries to access memory at address 8 => Segmentation fault
这必须
asm("movl $8,%ecx"); // Moves literal 8 into ecx
相应地调整所有其他指令。
另一个问题是下面的指令:
asm("cmpb 0,$esi"); // $esi is not a literal nor a register name
这必须
asm("cmpb $0,(%esi)"); // compare value at address stored in %esi with literal 0 (end of string)
我建议你编译调试信息的代码,例如
$ g++ -g -o sample sample.c
这是那么很容易调试该程序:
$ gdb sample
(gdb) run
Starting program: sample
sh: cls: command not found
Vvedite stroky iz 0 i 1 (do 8 delementov) > 10101010
Program received signal SIGSEGV, Segmentation fault.
main (argc=1, argv=0x7fffffffe238) at sample.c:18
18 asm("movl 8,%ecx"); // current bit position
如您所见,调试器向您显示导致分段错误的指令。
更新
的建议通过@Brett这为我工作,使用单一asm
语句中的汇编代码:
asm("leal s, %esi \n\t" // s => %esi
"movl $8, %ecx \n\t" // current bit position (+1)
"movl $0, %edx \n" // initialize result
"repeat: \n\t"
"movl $1, %eax \n\t" // Create bit mask in %eax
"dec %ecx \n\t" // Decrement rotation counter to shift mask bit to proper position
"rol %cl, %eax \n\t" // calculate value of current binary digit
"cmpb $0x31, (%esi) \n\t" // current digit == 1?
"jnz x \n\t" // no, skip
"add %eax, %edx \n" // add current value to %edx
"x: \n\t"
"inc %esi \n\t" // next address in input string
"cmpb $0, (%esi) \n\t" // end of string reached?
"jnz repeat \n\t" // no, continue
"movl %edx,a \n"); // store result in a variable
$ ./sample
Vvedite stroky iz 0 i 1 (do 8 delementov) > 10101010
4islo 170
我个人避免AT&T的语法,但不应该”你是用'$'加前缀所有立即数和所有带有'%'的寄存器吗? (例如,'cmpb 0,$ esi'这一行应该是'cmpb $ 0,%esi')。 – Michael
它看起来并不像我这样的代码真的非常接近完成这项工作。在你习惯于编写汇编语言之前,通常最简单的方法是用c,*来编写一些工作代码,然后编写代码(大致)在汇编语言中做同样的事情。 –
每个'asm'语句都是独立的。您不能假定寄存器保存您在每个“asm”块之前或之后所假设的值。您可能想阅读GCC内联程序集中的[* good * tutorial](http://locklessinc.com/articles/gcc_asm/)。 –