2014-01-08 63 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) –