簡體   English   中英

內聯匯編中的乘法指令錯誤

[英]multiplication instruction error in inline assembly

考慮以下程序:

#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) );的確切含義是:"=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”的操作數不匹配

那么,為什么我會收到此錯誤? 我該如何解決這個錯誤? 我已經在Google上搜索了這些內容,但找不到我的問題的解決方案。 我正在使用Windows 10 OS,處理器是Intel Core i3。

:“ = a”(foo)的確切含義是:“ a”(foo),“ b”(bar));

還有的參數是如何傳遞給匯編指令的詳細介紹在這里 簡而言之,就是說bar進入ebx寄存器, foo進入eax,在執行asm之后,eax將包含foo的更新值。

錯誤:“ mul”的操作數不匹配

是的,那不是mul的正確語法。 也許您應該花一些時間閱讀x86匯編程序參考手冊(例如this )。

我還要補充一點,使用內聯asm通常不是一個好主意


編輯:我無法在評論中加入對您問題的回答。

我不太確定從哪里開始。 這些問題似乎表明您根本不了解匯編程序的工作方式。 試圖通過SO答案教您asm編程不是很實際。

但我可以為您指明正確的方向。

首先,請考慮以下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)
                     );

通過使用“ a”約束,您正在要求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"
         );

如前所述,這會將bar放在ebx中,並將foo放在eax中,然后執行乘法指令。

在完成asm之后,eax將包含結果的下部,而edx將包含結果的下部。 如果foo * bar <2,147,483,647,則foo將包含您需要的結果,並且upper將為零。 否則,事情會變得更加復雜。

但這是我願意去的。 除此之外,參加ASM課程。 讀一本書。

附注:您可能還會看到答案以及隨后的3條注釋,這些注釋說明了為什么即使您的“添加”示例也是“錯誤的”。

PPS如果此答案解決了您的問題,請不要忘記單擊其旁邊的復選標記,以便獲得我的業障積分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM