私は、アセンブリプログラミングの初心者です。GNUアセンブラv2.20.1を使用して、Ubuntu x86_64デスクトップで Programming Ground Up を使用して作業しています。
スタックを操作するためにpushl/popl命令を使用するまで、コードをアセンブル/リンク実行できました。次のコードはアセンブルに失敗します:
.section .data # empty
.section .text
.globl _start
_start:
pushl $1 # Push the value 1 onto the stack
popl %eax # pop 1 off the stack and into the %eax register
int $0x80 # exit the program with exit code '1'
「test.s -o test.oとして」を使用すると、これらのエラーが端末に表示され、test.oは作成されません。
test.s: Assembler messages:
test.s:9: Error: suffix or operands invalid for 'Push'
test.s:10: Error: suffix or operands invalid for 'popl'
ドキュメントを確認しましたが、pushlとpoplに使用しているオペランドは有効です。これは正確にデバッグの質問ではありません-それで私のコードの何が問題になっていますか?それとも私のアセンブラですか?
64ビットモードでは、32ビット値をプッシュおよびポップできません。 pushq
とpopq
が必要です。
また、この方法では適切な出口が得られません。 32ビットx86では、exit()
システムコールを選択するために_%eax
_を1に設定する必要がありますand _%ebx
_を実際に必要な終了コードに設定します。 64ビットx86(これが使用しているもの)では、規則が異なります。exit()
のシステムコール番号は1ではなく60です。最初のシステムコールパラメータは_%rdi
_ではなく_%rbx
_に入ります。システムコール呼び出しのオペコードは_int $0x80
_ではなく、特別なx86-64のみのオペコードsyscall
です。
につながる:
_.section .data
.section .text
.globl _start
_start:
pushq $60
popq %rax
pushq $1
popq %rdi
syscall
_
(各Push
/pop
シーケンスは、単純なmov
(_mov $60, %eax
_のような)に置き換えることができます。もちろん、明示的にテストしようとしていると思いますPush
とpop
、コードサイズを最適化、またはマシンコードで_0
_バイトを回避(エクスプロイトペイロードの場合))
関連:
私も最近これらの例に従っています。
.code32
を追加します--32
フラグを使用してアセンブルする-m elf_i386
フラグとリンクするあなたは私の例を見ることができます ここ
プッシュ/ポップシーケンスを次のものに置き換える必要があります。
pushq $1 # Push the value 1 onto the stack
popq %rax # pop 1 off the stack and into the %eax register
エラーメッセージが「suffix or operand invalid」であることに注意してください。エラーメッセージの論理OR
の2番目の部分のみをチェックしました。おそらく、サフィックスが正確にわからなかったためですつまり、「l」です。
編集:コードがアセンブルされても機能しない理由の説明については、Thomasの回答を参照してください。
私は同じ本で作業中にこのエラーに遭遇しました。次のシェルスクリプト(att.sh)を作成しました。
#!/bin/sh
as --32 $1.s -o $1
ld -melf_i386 $1.o -o $1
./$1
echo $?
次に、実行可能にして実行しました(入力ファイルmyfile.sを想定)。
chmod +x ./att.sh
./att.sh myfile