アセンブリコードで「int0x80」とはどういう意味ですか?


回答:


69

割り込みベクタ0x80に制御を渡します

http://en.wikipedia.org/wiki/Interrupt_vectorを参照してください

Linuxでは、見ていこれを:それは処理するために使用されましたsystem_call。もちろん、別のOSでは、これはまったく異なることを意味する可能性があります。


5
だ短縮長い話で命令は意味それを行う命令には前でした。
Yuda Prawira 2011

2
@YudaPrawira:以前の命令は、レジスターに引数を設定すること、およびカーネル内の関数(によって選択される)int 0x80に対する特別な種類のものと考える必要があります。calleax
ピーターコーデス2018年

なぜ「使用された」と言ったのですか?もう使われていませんか?
リーガ

129

intは割り込みを意味し、番号0x80は割り込み番号です。割り込みは、その割り込みを処理している人(0x80この場合は割り込み)にプログラムフローを転送します。Linuxでは、0x80割り込みハンドラーはカーネルであり、他のプログラムによってカーネルへのシステムコールを行うために使用されます。

カーネルは、レジスターの値%eax(AT&T構文、およびIntel構文のEAX)を調べることにより、プログラムが実行したいシステムコールについて通知されます。各システムコールには、他のレジスタの使用に関して異なる要件があります。たとえば、1inの値%eaxはのシステムコールを意味し、exit()in%ebxの値はのステータスコードの値を保持しますexit()


47

ことを覚えておいてください0x80= 80h=128

あなたは見ることができ、ここでそのINTx86命令セットに存在するだけで、多くの命令の1つである(実際にはアセンブリ言語表現(または私はそれを「ニーモニック」)と言う必要があります)。この手順の詳細については、こちらにあるIntel独自のマニュアルを参照してください。

PDFから要約するには:

INT n / INTO / INT3-割り込みプロシージャの呼び出し

INT n命令は、デスティネーションオペランドで指定された割り込みまたは例外ハンドラへの呼び出しを生成します。デスティネーションオペランドは、0〜255のベクトルを指定し、8ビットの符号なし中間値としてエンコードされます。INT n命令は、ソフトウェアで生成された割り込みハンドラへの呼び出しを実行するための一般的なニーモニックです。

ご覧のとおり、0x80デスティネーションオペランドです。質問のです。この時点で、CPUは、カーネルに存在するコードを実行する必要があることを認識していますが、どのコードですか?これは、Linuxの割り込みベクタによって決定されます。

最も有用なDOSソフトウェア割り込みの1つは、割り込み0x21でした。レジスタ内のさまざまなパラメータ(主にahとal)を使用して呼び出すことにより、さまざまなIO操作、文字列出力などにアクセスできます。

ほとんどのUnixシステムおよび派生物は、システムコールを行うために使用される割り込み0x80を除いて、ソフトウェア割り込みを使用しません。これは、カーネル関数に対応する32ビット値をプロセッサのEAXレジスタに入力してから、 INT0x80を実行することによって実現されます。

割り込みハンドラテーブルで利用可能な他の値が示されている場所で、これを見てください。

ここに画像の説明を入力してください

ご覧のとおり、表はシステムコールを実行するCPUを示しています。Linuxシステムコールの表はここにあります

したがって、値0x1をEAXレジスタに移動し、プログラムでINT 0x80を呼び出すことにより、現在実行中のプロセス(Linux、x86 Intel CPU)を停止(終了)するカーネル内のコードをプロセスに実行させることができます。

ハードウェア割り込みをソフトウェア割り込みと混同しないでください。これは、この点に関して非常に良い答えです。

これも良い情報源です。


4
Linuxシステムコールテーブルのリンクが壊れています= \
Miguel Angelo

1
ほとんどのUnixシステムと派生物はソフトウェア割り込みを使用しません(int 0x80を除く)それを置くための奇妙な方法のようです。int 0x80i386のLinuxシステムコールABIは、DOSに非常に似ているint 0x21ABI。レジスタ(DOSの場合はAH、Linuxの場合はEAX)に呼び出し番号を入れ、他のレジスタに他の引数を入れてから、ソフトウェア割り込み命令を実行します。主な違いは、システムコールで実行できること(LinuxではなくDOSでハードウェアに直接アクセスすること)であり、呼び出す方法ではありません。
ピーターコーデス2017

これは壊れていないsyscallテーブルのリンクです。syscalls.kernelgrok.com展開すると、すべての通話が上部に表示されます。
ollien

Linux 64ビットを使用している場合、/usr/include/x86_64-linux-gnu/asm/unistd_64.h
トンで

11

最小限の実行可能なLinuxシステムコールの例

Linuxは0x80、ユーザーランドプログラムがカーネルと通信する方法であるシステムコールを実装するように割り込みハンドラーを設定します。

.data
    s:
        .ascii "hello world\n"
        len = . - s
.text
    .global _start
    _start:

        movl $4, %eax   /* write system call number */
        movl $1, %ebx   /* stdout */
        movl $s, %ecx   /* the data to print */
        movl $len, %edx /* length of the buffer */
        int $0x80

        movl $1, %eax   /* exit system call number */
        movl $0, %ebx   /* exit status */
        int $0x80

コンパイルして実行する:

as -o main.o main.S
ld -o main.out main.o
./main.out

結果:プログラムはstdoutに出力します:

hello world

きれいに終了します。

リング3しかないため、ユーザーランドから直接独自の割り込みハンドラーを設定することはできません。Linuxでは設定できません。

GitHubアップストリーム。Ubuntu16.04でテスト済み。

より良い選択肢

int 0x80システムコールを行うためのより良い代替手段に取って代わられました:最初にsysenter、次にVDSO。

x86_64に新しいsyscall命令があります。

参照:「int0x80」または「syscall」の方が優れていますか?

最小限の16ビットの例

まず、ここで説明したように、最小限のブートローダーOSを作成し、QEMUと実際のハードウェアで実行する方法を学びます:https//stackoverflow.com/a/32483545/895245

これで、16ビットリアルモードで実行できます。

    movw $handler0, 0x00
    mov %cs, 0x02
    movw $handler1, 0x04
    mov %cs, 0x06
    int $0
    int $1
    hlt
handler0:
    /* Do 0. */
    iret
handler1:
    /* Do 1. */
    iret

これは順番に行います:

  • Do 0.
  • Do 1.
  • hlt:実行を停止します

プロセッサがアドレス0で最初のハンドラーを検索し、4:で2番目のハンドラーを検索する方法に注意してください。これはIVTと呼ばれるハンドラーのテーブルであり、各エントリには4バイトがあります。

一部のIOを実行する最小限の例ハンドラーを表示するためにを実行する。

最小限の保護モードの例

最新のオペレーティングシステムは、いわゆるプロテクトモードで実行されます。

このモードでは、処理に多くのオプションがあるため、より複雑になりますが、精神は同じです。

重要なステップは、ハンドラーを記述するメモリ内データ構造(割り込み記述子テーブル)のアドレスを指すLGDTおよびLIDT命令を使用することです。

最小限の例



4

「int」命令は割り込みを引き起こします。

割り込みとは何ですか?

簡単な答え:簡単に言えば、割り込みはCPUに割り込みをかけ、特定のタスクを実行するように指示するイベントです。

詳細な回答

CPUには、メモリに格納された割り込みサービスルーチン(またはISR)のテーブルがあります。REAL(16ビット)モードでは、これは次のように格納されているIVT、又はI nterrupt VエクターTができます。IVTは通常、0x0000:0x0000(物理アドレス0x00000)にあり、ISRを指す一連のセグメントオフセットアドレスです。OSは、既存のIVTエントリを独自のISRに置き換える場合があります。

(注:IVTのサイズは1024(0x400)バイトに固定されています。)

保護(32ビット)モードでは、CPUはIDTを使用します。IDTは、記述子で構成される可変長構造です。、割り込みハンドラーについてCPUに通知する(別名ゲート)で。これらの記述子の構造は、IVTの単純なセグメントオフセットエントリよりもはるかに複雑です。ここにあります:

bytes 0, 1: Lower 16 bits of the ISR's address.
bytes 2, 3: A code segment selector (in the GDT/LDT)
byte 4: Zero.
byte 5: A type field consisting of several bitfields.
    bit 0:  P (Present): 0 for unused interrupts, 1 for used interrupts.*
    bits 1, 2: DPL (Descriptor Privilege Level): The privilege level the descriptor (bytes 2, 3) must have.
    bit 3: S (Storage Segment): Is 0 for interrupt and trap gates. Otherwise, is one. 
    bits 4, 5, 6, 7: GateType:
        0101: 32 bit task gate
        0110: 16-bit interrupt gate
        0111: 16-bit trap gate
        1110: 32-bit interrupt gate
        1111: 32-bit trap gate
 

* IDTは可変サイズの場合がありますが、シーケンシャルである必要があります。つまり、IDTを0x00から0x50までと宣言する場合は、0x00から0x50までのすべての割り込みが必要です。OSは必ずしもそれらすべてを使用するわけではないため、Presentビットを使用すると、CPUはOSが処理する予定のない割り込みを適切に処理できます。

割り込みが発生したとき(IRQの外部トリガー(ハードウェアデバイスなど)によって、または intプログラムから命令の)、CPUはEFLAGS、CS、EIPの順にプッシュします。(これらはによって自動的に復元されますiret、割り込みリターン命令ます。)OSは通常、マシンの状態に関する詳細情報を格納し、割り込みを処理し、マシンの状態を復元して、続行します。

多くの* NIX OS(Linuxを含む)では、システムコールは割り込みベースです。プログラムは、システムコールの引数をレジスタ(EAX、EBX、ECX、EDXなど)に入れ、割り込み0x80を呼び出します。カーネルは、0x80に割り込みハンドラーを含むようにIDTを既に設定しています。これは、割り込み0x80を受信したときに呼び出されます。次に、カーネルは引数を読み取り、それに応じてカーネル関数を呼び出します。返品はEAX / EBXに保存される場合があります。システムコールの大部分はsysenterand sysexit(またはsyscallandsysretリング0に速く進入を可能命令、AMDの上)。

この割り込みは、OSによって意味が異なる可能性があります。必ずドキュメントを確認してください。


おもしろい事実:FreeBSDのi386システムコールABIは、ユーザースペーススタックに引数を渡します。eaxシステムコール番号にのみ使用されます。 asm.sourceforge.net/intro/hello.html
Peter Cordes

2

前述のように、制御は割り込みベクトル0x80にジャンプします。実際には、これが意味することは(少なくともLinuxでは)システムコールが呼び出されることです。正確なシステムコールと引数は、レジスタの内容によって定義されます。たとえば、exit()は、%eaxを1に設定し、その後に「int0x80」を設定することで呼び出すことができます。


1

これは、CPUに割り込みベクトル0x80をアクティブにするように指示します。これは、Linux OSではシステムコール割り込みであり、open()ファイルなどのシステム関数を呼び出すために使用されます。


9
厳密に言えば、カーネルには通知しません... IDTでハンドラーを検索するCPUに通知し、最終的にはカーネルコードへのポインターになります。
asveikau 2009年

本当。より良い言い回しは、CPUにベクターをアクティブ化するように指示し、ベクター(カーネルの一部として)が関数を呼び出すことだと思います。
琥珀

これを行うことになり、次にそれを行うことになり、次にこれを行い、それが混乱してそこに行きます。:/アンバーはunderstandable..thatsそれ...です答えている
AfzaalアフマドZeeshan

1

intは中断に他なりません。つまり、プロセッサは現在の実行を保留にします。

0x80は、システムコールまたはカーネルコールに他なりません。つまり、システム機能が実行されます。

具体的には、0x80はrt_sigtimedwait / init_module / restart_sysを表し、アーキテクチャごとに異なります。

詳細については、https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.mdを参照してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.