Есть некоторые проблемы с этим кодом - в моей системе он даже не прошел через компилятор/ассемблер. Основная проблема заключается в том, что вам нужно ставить перед всеми литералами префикс $
, иначе ассемблер предполагает доступ к памяти:
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
Как видите, отладчик показывает инструкцию, вызвавшую ошибку сегментации.
Обновить
Код сборки, который работал у меня, используя один оператор asm
, предложенный @Brett:
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
08.01.2014
cmpl $31,%esi
должно бытьcmpb $31,(%esi)
(косвенная адресация), и то же самое дляcmpl $0,%esi
должно бытьcmpb $0,(%esi)
09.01.2014$31
также должно быть$0x31
(шестнадцатеричное значение0x31
— это ASCII 1, а не десятичное значение31
) 09.01.2014