2017-02-16 82 views
0

請考慮下面的程序:乘法指令錯誤

#include <stdio.h> 
int main(void) { 
     int foo = 10, bar = 15; 
     __asm__ __volatile__("add %%ebx,%%eax" 
          :"=a"(foo) 
          :"a"(foo), "b"(bar) 
          ); 
     printf("foo+bar=%d\n", foo); 
} 

我知道add指令用於另外,sub指令用於減法&等。但我不明白這些行:

__asm__ __volatile__("add %%ebx,%%eax" 
          :"=a"(foo) 
          :"a"(foo), "b"(bar) 
          ); 

什麼是:"=a"(foo) :"a"(foo), "b"(bar));的確切含義是什麼?它能做什麼 ?當我嘗試使用mul指令在這裏我獲得以下以下程序錯誤:

#include <stdio.h> 
int main(void) { 
     int foo = 10, bar = 15; 
     __asm__ __volatile__("mul %%ebx,%%eax" 
          :"=a"(foo) 
          :"a"(foo), "b"(bar) 
          ); 
     printf("foo*bar=%d\n", foo); 
} 

錯誤:'MUL」

那麼,爲什麼我收到此錯誤的操作數不匹配的號碼?我該如何解決這個錯誤?我在谷歌搜索這些,但我找不到解決我的問題。我使用的是Windows 10操作系統&處理器是英特爾酷睿i3。

回答

4

What is the exact meaning of :"=a"(foo) :"a"(foo), "b"(bar));

有關如何將參數傳遞給asm指令here的詳細說明。簡而言之,這表示bar進入ebx寄存器,foo進入eax,並且在執行asm後,eax將包含foo的更新值。

Error: number of operands mismatch for `mul'

是的,這不是mul的正確語法。也許你應該花一些時間用x86彙編參考手冊(例如,this)。

我還補充說使用內聯asm通常是bad idea


編輯:我無法對您的問題做出迴應。

我不太確定從哪裏開始。這些問題似乎表明,您對彙編程序的工作方式沒有很好的掌握。試圖在SO答案中教你ASM編程並不實際。

但我可以指出你在正確的方向。

首先,考慮此位的彙編代碼:

movl $10, %eax 
movl $15, %ebx 
addl %ebx, %eax 

你明白做什麼?當這個完成時,eax中會有什麼? ebx中會有什麼?現在,比較,與此:

int foo = 10, bar = 15; 
__asm__ __volatile__("add %%ebx,%%eax" 
        :"=a"(foo) 
        :"a"(foo), "b"(bar) 
        ); 

通過使用「一」的約束,你問的gcc來的foo值移入EAX。通過使用「b」限制,您要求它將bar轉換爲ebx。它執行此操作,然後執行asm的指令(即add)。退出asm後,foo的新值將在eax中。得到它?

現在,讓我們看看mul。根據我與您聯繫的文檔,我們知道語法是mul value。這似乎很奇怪,不是嗎? mul只能有一個參數?它是多少值

但是,如果你繼續讀,你會看到「始終由值相乘EAX。」啊。所以「eax」寄存器總是隱含在這裏。所以,如果你寫mul %ebx,那真的會平均mul ebx, eax,但因爲它總是是EAX,有它寫出來沒有真正的點。

但是,它比這更復雜一點。 ebx可以保存一個32位的數值。由於我們使用整數(而不是無符號整數),這意味着ebx可以有一個大到2,147,483,647的數字。但是等等,如果你乘以2,147,483,647 * 10會發生什麼?那麼,因爲2,147,483,647已經可以存儲在一個寄存器中,所以它的結果太大了,不適合eax。所以乘法(總是)使用2個寄存器來輸出mul的結果。當它提到「將結果存儲在EDX:EAX中」時,這就是該鏈接的含義。

所以,你可以寫你的乘法是這樣的:正如前面

int foo = 10, bar = 15; 
int upper; 
__asm__ ("mul %%ebx" 
     :"=a"(foo), "=d"(upper) 
     :"a"(foo), "b"(bar) 
     :"cc" 
     ); 

,這使酒吧EBX和Foo在EAX,然後執行乘法指令。

和ASM完成後,EAX將包含結果的下部和EDX將包含上。如果foo * bar < 2,147,483,647,那麼foo將包含您需要的結果並且upper將爲零。否則,事情變得更加複雜。

但是,這是因爲就我願意去。除此之外,參加一個asm課程。讀一本書。

PS你也可能看this答案並遵循展會的3條評論爲什麼連「加入」的例子是「錯誤的」。

PPS如果這個答案已經解決了你的問題,不要忘記點擊旁邊的選中標記,所以我讓我的榮譽點數。

+0

這裏「a」和「b」表示什麼? – Destructor

+0

如果您閱讀了鏈接到asm的文檔,您將看到引用的字符串是描述如何將C語言變量映射到asm可以理解的東西的「約束」(參見i386部分[here](https:// gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html))。 「a」是指eax寄存器。 「b」是指ebx。 –

+0

好的謝謝。我知道了。但我仍然有一個問題。我想將foo和bar變量的值與foo中的結果相乘。我已經訪問了您提供的有關多次違規的鏈接,但是我仍然很難知道我應該怎麼做才能做到這一點? – Destructor