2014-01-08 64 views
0

所以我对这段代码有问题。这是一个从二进制转换为deximal数字的程序。ASM at&t语法

#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算子中存在这个问题。

+2

我个人避免AT&T的语法,但不应该”你是用'$'加前缀所有立即数和所有带有'%'的寄存器吗? (例如,'cmpb 0,$ esi'这一行应该是'cmpb $ 0,%esi')。 – Michael

+0

它看起来并不像我这样的代码真的非常接近完成这项工作。在你习惯于编写汇编语言之前,通常最简单的方法是用c,*来编写一些工作代码,然后编写代码(大致)在汇编语言中做同样的事情。 –

+1

每个'asm'语句都是独立的。您不能假定寄存器保存您在每个“asm”块之前或之后所假设的值。您可能想阅读GCC内联程序集中的[* good * tutorial](http://locklessinc.com/articles/gcc_asm/)。 –

回答

1

该代码存在一些问题 - 在我的系统中,它甚至没有运行编译器/汇编程序。主要的问题是,你需要$前缀的所有文字,否则汇编器总是假设一个内存访问:

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 
+0

我改变了这段代码并编译了它,但它给出了一个零。 \t ASM( “MOVL $ 8%ECX”); \t ASM( “MOVL $ 0,%EDX”); \t ASM( “重复:”); \t ASM( “MOVL $ 1,%eax中”); \t ASM( “DEC%ECX”); \t ASM( “ROL%的Cl,%eax中”); \t ASM( “CMPL $ 31%ESI”); \t ASM( “JNZ X”); \t ASM (“add%eax,%edx”); \t asm(“x:”); \t asm(“incl%esi”); \t asm(“cmpl $ 0,%esi”); \t asm(“jnz repeat”); \t asm(“movl%edx,a”); \t printf(“4islo%d \ n”,a); – Viodentia

+0

'cmpl $ 31,%esi'需要为'cmpb $ 31,(%esi)'(间接寻址),对于'cmpl $ 0,%esi'也是一样的,这需要'cmpb $ 0,(%esi)'' –

+0

请注意'$ 31'也需要'$ 0x31'(十六进制值0x31是ASCII码1,而不是十进制值31) –