GCC は AT&T スタイルのアセンブリで最適に動作し、GAS はすべての Intel 構文を実装しているわけではありません。あなたの差し迫った問題は110b
、数字として解釈されないことに起因しますが、それだけではありません.
GCC のインライン アセンブラー構文では、変数を直接参照することはできません。次のように記述する必要があります (デフォルトを使用-masm=att
):
int foobar(int num) {
int result;
asm("mov %1, %%eax\n\t"
"add $6, %%eax\n\t"
"sub $2, %%eax\n\t"
"mov %%eax, %0"
: "=g" (result)
: "g" (num)
: "eax", "cc");
return result;
}
最初のコロンの後には、出力オペランドのコンマ区切りリストがあります。"=g" (result)
が最初の制約であるため、 result
alias を取得し%0
ます。 任意の汎用レジスタまたはメモリである可能性があり、書き込みのみが行われる"=g"
GCC に示します。%0
(+
代わりに、=
読み書きを示します。GCC は複数の目的で同じレジスタを再利用することを決定する場合があるため、すべてがどのように使用されるかを正確に伝えることを明示する必要があります。)
2 番目のコロンの後には、入力オペランドのコンマ区切りリストがあります。"g" (num)
は 2 番目の制約であるため、 num
alias を取得し%1
ます。 "g"
からのみ読み取られることを意味します。
3 番目のコロンの後には、クロバーのカンマ区切りリストがあります。これは、インラインアセンブリがこれらのレジスタ/メモリを入力でも出力でもない場合でも変更する可能性があることを GCC に通知するため、GCC はインラインアセンブリ全体で保持していた情報を再ロードする必要があります。ここでは、明らかに を変更%eax
し、条件コード (フラグ) レジスタも の影響を受けadd/sub
ます。
コンパイラが生成するアセンブリを見てください。
$ cc -S -o- -m32 asmtest.c | sed -n /globl.foobar/,/-foobar/p
.globl フーバー
.type foobar、@関数
フーバー:
pushl %ebp
movl %esp, %ebp
サブル $16、%esp
#アプリ
#15「asmtest.c」1
mov 8(%ebp), %eax
$6、%eax を追加
サブ $2、%eax
mov %eax, -4(%ebp)
#0""2
#NO_APP
movl -4(%ebp), %eax
離れる
戻る
.size foobar、.-foobar
コンパイラは、 と のスタック位置を直接使用することを決定しましnum
たresult
。:"=r":"r"
(レジスタまたはメモリ位置を許可する) 代わりに制約 (レジスタのみが許可されることを意味する)を使用した場合:"=g":"g"
、コンパイラはインライン アセンブリの前後にそれらをレジスタとの間でコピーします。
$ cc -S -o- -m32 asmtest.c | sed -n /globl.foobar/,/-foobar/p
.globl フーバー
.type foobar、@関数
フーバー:
pushl %ebp
movl %esp, %ebp
サブル $16、%esp
movl 8(%ebp)、%edx
#アプリ
#15「asmtest.c」1
mov %edx, %eax
$6、%eax を追加
サブ $2、%eax
mov %eax, %edx
#0""2
#NO_APP
movl %edx, -4(%ebp)
movl -4(%ebp), %eax
離れる
戻る
.size foobar、.-foobar
本当に Intel 構文を使用したい場合は、それを別の.s
ソース ファイルに入れ、 NASMで個別にアセンブルしてから、オブジェクトをリンクしてください。
$猫 asmtest.c
#include <stdio.h>
int foobar(int);
/* int foobar(int) __attribute__((fastcall)); */
int main() {
int n = 0;
printf("番号: ");
scanf("%d", &n);
printf("%d\n", foobar(n));
0 を返します。
}
$ cat foobar.s
グローバルフーバー
フーバー:
mov eax,[esp+4] # C プロトタイプが fastcall とマークされている場合、この行を削除します
サブ eax、110b
eax,2 を追加
戻る
$ nasm -f elf foobar.s
$ cc -m32 asmtest.c foobar.o
$ ./a.out
番号: 30
26
(ただし-f elf
、Windows では正しくありません。たぶん-f win32
? Windows の愚かさのために_foobar
、アセンブリで名前を使用する必要がある場合があります。)