2011-08-01 10 views
5

私は参考文献が必要ですが、いい例もあります。 NASMアセンブラを使用してアセンブリでコードを記述し始めているので、必要です。syscallsの良いリファレンス

http://bluemaster.iu.hio.no/edu/dark/lin-asm/syscalls.html

非常に素晴らしく、便利ですが、それは他のレジスタ内のフィールドを説明していないので、それが限界をたくさん持っている:私は、この参照を持っています。たとえば、私がwriteシステムコールを使用している場合、私はEAXレジスタに1を入れて、ECXはおそらく文字列へのポインタですが、EBXとEDXはどうでしょうか? EBXが入力を決定する(stdinは0、その他は1など)、EDXは入力する文字列の長さなどです。私が望むものを理解してくれることを願っています。私はそのような資料を見つけることができなかったので、私はここに書いています。 ありがとうございます。あなたがそのWebページをダウンロードする(それが第二段落に示唆のような)とカーネルソースをダウンロードした場合

答えて

0

、あなたは「ソース」列のリンクをクリックして、システムコールを実装するソースファイルに直接行くことができます。 Cのシグネチャを読んで、各パラメータの使用方法を確認できます。

クイックリファレンスを探しているだけの場合、これらのシステムコールのそれぞれは、同じ名前からsys_を差し引いたCライブラリインターフェイスを持っています。したがって、たとえば、あなたがsys_lseekのパラメータに関する情報を取得するためにman 2 lseekをチェックアウトすることができます:あなたが見ることができるように、パラメータは、あなたのHTMLのテーブルからのものと一致し、

off_t lseek(int fd, off_t offset, int whence); 

%ebx   %ecx %edx 
unsigned int off_t unsigned int 
+0

Googleの検索エンジンやソースコード検索のエンゲージメントでも、それらがどのように使用されているのかの直接的な例を見つけることができます。私のポストのポイントは、いくつかの素晴らしいチートシートで検索と分析をスキップすることです。ありがとう。 –

11

Linuxの標準的なプログラミング言語はCです。そのため、システムコールの最善の記述では、C関数を呼び出すように表示されます。 C関数としての記述と、アセンブリで実際のシステムコールにそれらをマップする方法の知識があれば、簡単に望む任意のシステムコールを使用することができます。

まず、Cプログラマに見えるように、すべてのシステムコールの参照が必要です。私が知っている最良のものは、Linux man-pages project、特にsystem callsセクションです。

は、それはあなたの問題の一つであるためのが、一例としてwriteシステムコールを見てみましょう。ご覧のとおり、最初のパラメータは符号付き整数で、通常はopenシステムコールによって返されるファイル記述子です。これらのファイル記述子は、通常、最初の3つのファイル記述子(0 = stdin、1 = stdout、2 = stderr)で発生するように、親プロセスから継承されている可能性があります。 2番目のパラメータはバッファへのポインタで、3番目のパラメータはバッファのサイズ(符号なし整数)です。最後に、関数は符号付き整数を返します。符号付き整数は、書き込まれたバイト数またはエラーの負数です。

これを実際のシステムコールにどのようにマップするのですか? 32ビットx86上でシステムコールを行う方法はたくさんあります(これはおそらくあなたのレジスタ名に基づいています)。 64ビットx86では完全に異なっていることに注意してください(32ビットモードでアセンブルして32ビット実行ファイルをリンクすることを忘れないでください;そうでないと状況が変わる例についてはthis questionを参照してください)。 32ビットx86の中で最も古く、最も単純で遅いのは、int $0x80メソッドです。int $0x80方法については

、あなたはそのためには、%ebx%ecx%edx%esi%edi、および%ebp%eaxでシステムコール番号、およびパラメータを置きます。その後、int $0x80を呼び出し、システムコールの戻り値は%eaxです。この戻り値はとは異なり、とは異なります。このリファレンスはCライブラリがどのようにそれを返すかを示していますが、システムコールはエラー時に-errnoを返します(例えば-EINVAL)。この場合、Cライブラリはerrnoに移動し、-1を返します。詳細については、syscalls(2)およびintro(2)を参照してください。

ので、write例では、あなたが(%eaxwriteシステムコール番号、%ebxの最初のパラメータ(ファイル記述子番号)、%ecxの2番目のパラメータ(文字列へのポインタ)、3番目のパラメータを置きます文字列の長さ)を%edxに設定します。 %eaxには、書き込まれたバイト数か、エラー番号がネゲートされます(戻り値が-1〜-4095の場合は、ネゲートされたエラー番号です)。

最後に、システムコール番号はどのようにして見つけられますか?それらは/usr/include/linux/unistd.hで見つけることができます。私のシステムでは、これはちょうど/usr/include/asm/unistd_32.hを含む/usr/include/asm/unistd.hを含んでいるので、数字はそこにあります(writeの場合、__NR_write4です)。 /usr/include/linux/errno.h(私のシステムでは、最初のものが/usr/include/asm-generic/errno-base.h、残りが/usr/include/asm-generic/errno.hであることがわかります)のエラー番号も同じです。他の定数や構造体を使用するシステムコールでは、対応する定義を見つけるためにどのヘッダを調べるべきかを文書に記述しています。


今のところ、私が言ったように、int $0x80は最も古くて遅い方法です。より新しいプロセッサには特別なシステムコール命令があり、高速です。それらを使用するために、カーネルは、あなたのハードウェアで利用可能な最良の方法を使ってシステムコールを行うために呼び出すことのできる仮想ダイナミック共有オブジェクト(vDSO;共有ライブラリのようですが、メモリのみ)を利用できます。また、システムコールや他のいくつかのことをすることなく、現在の時刻を取得するための特別な機能を提供します。もちろん、動的リンカーを使用していない場合は、使用するのが少し難しくなります。

もう1つ古い方法であるvsyscallは、vDSOに似ていますが、固定アドレスで1ページを使用します。最近のカーネルを使用している場合はシステムログに警告が表示され、さらに最近のカーネルではブート時に無効になり、将来は削除される可能性があります。それを使用しないでください。

+0

これは私が今までに見た中で最高の答えの一つです。 –

関連する問題