[英]Using AT&T inline assembler for GCC
我正在編寫一個簡單但有點具體的程序:
目的:根據階乘計算數字
要求:所有計算都必須在gcc內聯asm上完成(at&t語法)
源代碼:
#include <iostream>
int main()
{
unsigned n = 0, f = 0;
std::cin >> n;
asm
(
"mov %0, %%eax \n"
"mov %%eax, %%ecx \n"
"mov 1, %%ebx \n"
"mov 1, %%eax \n"
"jmp cycle_start\n"
"cycle:\n"
"inc %%ebx\n"
"mul %%ebx\n"
"cycle_start:\n"
"cmp %%ecx, %%eax\n"
"jnz cycle\n"
"mov %%ebx, %1 \n":
"=r" (n):
"r" (f)
);
std::cout << f;
return 0;
}
此代碼導致SIGSEV。
使用intel asm語法的完全相同的程序( http://pastebin.com/2EqJmGAV )可以正常工作。 為什么我的“ AT&T程序”失敗了,我該如何解決?
#include <iostream>
int main()
{
unsigned n = 0, f = 0;
std::cin >> n;
__asm
{
mov eax, n
mov ecx, eax
mov eax, 1
mov ebx, 1
jmp cycle_start
cycle:
inc ebx
mul ebx
cycle_start:
cmp eax, ecx
jnz cycle
mov f, ebx
};
std::cout << f;
return 0;
}
UPD:推入堆棧並還原使用過的寄存器將得到相同的結果:SIGSEV
您的輸入和輸出方式錯誤。
所以,從改變開始
"=r" (n):
"r" (f)
至:
"=r" (f) :
"r" (n)
然后,我懷疑您將要告訴編譯器有關Clobbers(您正在使用的不是輸入或輸出的寄存器):
因此添加:
: "eax", "ebx", "ecx"
在以上兩行之后。
我個人將做出其他一些更改:
1:
和2:
等),這樣可以復制代碼而無需“重復標簽”。 %1
代替%%ebx
這樣,您就不會使用額外的寄存器。 %0
直接移動到%%ecx
。 要裝載1
到%%eax
兩個指令后,所以有它得到了在做什么樣的目的%%eax
? [現在,我寫的太多了,其他人先回答了...]
編輯:而且,正如安東指出,需要$1
加載常數1, 1
是指從地址1,讀不很好地工作,而且最有可能是你的問題的原因
希望沒有要求,只使用gcc inline asm來解決它。 您可以使用nasm
轉換您的AT&T示例,然后使用objdump
進行反匯編並查看正確的語法。
我似乎還記得,如果您的意思是字面常量而不是內存引用mov 1,%eax
那么mov 1,%eax
應該是mov $1,%eax
。
@MatsPetersson的答案對於內聯程序集與編譯器(填充/輸入/輸出寄存器)的交互非常有用。 我一直在關注您得到SIGSEGV
的原因,並且讀取地址1
確實可以回答問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.