ASM at& t语法

时间:2014-01-08 15:39:41

标签: c++ unix assembly

所以我对这段代码有疑问。这是一个从二进制转换为近数的程序。

#include <cstdlib>
#include <iostream>
#include <cstdio>

char s[100];
    int length;
    int a;


int main(int argc, char *argv[])
{

    system("cls");
    printf("\n\n  Vvedite stroky iz 0 i 1 (do 8 delementov) > ");
    gets(s);

    asm("leal s,%esi");
    asm("movl 8,%ecx");
    asm("movl 0,%edx");
    asm("repeat:");
    asm("movl 1,%eax");
    asm("dec %ecx");
    asm("rol %cl,%eax");
    asm("cmpb 31,%esi");
    asm("jnz x");
    asm("add %eax,%edx");
    asm("x: inc %esi");
    asm("cmpb 0,$esi");
    asm("jnz repeat");
    asm("movl %edx,a");

    printf("4islo %d",a);

    return EXIT_SUCCESS;
}

它给了我: “分段错误(核心转储)”

请帮助解决此ASM部分。 我认为CMPB运算符存在问题。

1 个答案:

答案 0 :(得分:2)

该代码存在一些问题 - 在我的系统上,它甚至没有通过编译器/汇编程序运行。主要问题是您需要在所有文字前加$,否则汇编程序会假定存储器访问:

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