Frage

Kann jemand erklären, was der folgende Assembler-Code funktioniert?

 int 0x80  
War es hilfreich?

Lösung

Es geht Kontrollvektor 0x80 zu unterbrechen

Siehe http://en.wikipedia.org/wiki/Interrupt_vector

Unter Linux haben Sie einen Blick auf dieser : es verwendet wurde system_call zu handhaben. Natürlich auf einem anderen Betriebssystem dies etwas ganz anderes bedeuten könnte.

Andere Tipps

int Mittel unterbrechen, und die Zahl 0x80 ist die Interrupt-Nummer. Eine Interrupt-Übertragungen der Programmablauf zu wem auch immer, dass die Interrupt Handling, das Interrupt 0x80 in diesem Fall ist. Unter Linux sind 0x80 Interrupt-Handler die Kernel und wird verwendet, Systemaufrufe an den Kernel von anderen Programmen zu machen.

Der Kernel über benachrichtigt wird, welches System rufen das Programm machen will, indem er den Wert in dem Register %eax Prüfung (Gas Syntax und EAX in Intel-Syntax). Jeder Systemaufruf hat unterschiedliche Anforderungen über die Verwendung der anderen Register. Zum Beispiel bedeutet ein Wert von 1 in %eax einen Systemaufruf von exit() und der Wert in %ebx hält den Wert des Statuscodes für exit().

Halten Sie

Sie daran, dass 0x80 = 80h = 128

Sie sehen hier dass INT ist nur eine der vielen Anweisungen (eigentlich der Assembly Language Darstellung (oder sollte ich sagen ‚mnemonic‘) davon), die in dem x86-Befehlssatz vorhanden ist. Sie können auch weitere Informationen zu dieser Anweisung in Intels eigenem Handbuch finden gefunden hier .

Um aus der PDF zusammenfassen:

  

INT n / IN / INT 3-Call-Verfahren zu unterbrechen

     

Die INT n Instruktion erzeugt einen Aufruf an die Unterbrechung oder Ausnahme   Handler mit dem Zieloperanden spezifiziert. Das Ziel   Operand gibt einen Vektor von 0 bis 255, codiert als 8-Bit-Ganz   Zwischenwert. Der INT n-Befehl ist die allgemeine Mnemonik für   ein Software-generierten Anruf an einen Interrupt-Handler ausgeführt wird.

Wie Sie sehen können 0x80 ist der Zieloperand in Ihrer Frage. An dieser Stelle weiß die CPU, dass es sollte einige Codes ausführen, die im Kernel befindet, aber was Code? Dies wird durch den Interrupt-Vektor in Linux bestimmt.

Eine der nützlichsten DOS Software-Interrupts war Interrupt 0x21. Indem sie sie mit unterschiedlichen Parametern in den Registern Aufruf (meist ah und al) Sie verschiedene IO-Operationen, String ausgegeben und mehr.

zugreifen können

Die meisten Unix-Systeme und Derivate keine Software-Interrupts, mit Ausnahme von Interrupt 0x80 verwendet, um Systemaufrufe machen verwenden. Dies wird erreicht, indem einen 32-Bit-Wert der Eingabe zu einer Kernfunktion in das EAX-Register des Prozessors entspricht und dann Ausführen INT 0x80.

Schauen Sie sich diese bitte, wo weitere Werte in der Interrupt-Handler-Tabellen angezeigt werden:

eingeben Bild Beschreibung hier

Wie Sie die Tabellenpunkte die CPU sehen einen Systemaufruf auszuführen. Sie können die Linux-System Call-Tabelle finden hier .

So durch den Wert 0x1 bewegt registrieren EAX und das INT 0x80 in Ihrem Programm aufrufen, können Sie den Prozess machen gehen Sie den Code in Kernel ausführen, die (exit) stoppt den laufenden Prozess (unter Linux, x86 Intel CPU) .

Ein Hardware-Interrupt darf nicht mit einem Software-Interrupt verwechselt werden. Hier eine sehr gute Antwort auf dieser Hinsicht.

Diese ist auch gute Quelle.

Sie können sehen int 80h in Aktion hier .

  

int 0x80 ist die Assemblersprache   Anweisung, die verwendet wird zum Aufruf   Systemaufrufe in Linux auf x86 (das heißt,   Intel-kompatiblen) Prozessoren.

http://www.linfo.org/int_0x80.html

Minimal runnable Linux-Systemaufruf Beispiel

Linux setzt die Interrupt-Handler für 0x80 oben, so dass sie Systemaufrufe implementiert, eine Möglichkeit für Userland-Programme mit dem Kernel zu kommunizieren.

.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

Kompilieren und Ausführen mit:

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

Ergebnis: Das Programm druckt nach stdout:

hello world

und verlässt sauber.

Sie können nicht Ihre eigenen Interrupt-Handler direkt von Userland gesetzt, weil Sie nur eine href haben <= "https://stackoverflow.com/questions/18717016/what-are-ring-0-and-ring-3-in- the-Kontext-of-Betriebssysteme / 44483439 # 44483439" > Ring 3 und Linux verhindert, dass Sie tun so .

GitHub Upstream . Getestet auf Ubuntu 16.04.

Bessere Alternativen

ersten int 0x80, dann VDSO

sysenter wurde für die Herstellung von Systemaufrufen durch bessere Alternativen ersetzt.

x86_64 hat ein neu syscall Anweisung .

Siehe auch: Was ist besser "int 0x80" oder "SYSCALL"?

Minimal 16-Bit-Beispiel

Zuerst lernen, wie man einen minimalen OS-Bootloader erstellen und auf QEMU und reale Hardware läuft, wie ich hier erklärt habe: https: / /stackoverflow.com/a/32483545/895245

Jetzt können Sie in 16-Bit-Real-Modus ausgeführt werden:

    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

Dies würde tun, um:

  • Do 0.
  • Do 1.
  • hlt: stop Ausführung

Beachten Sie, wie der Prozessor zum ersten Handler an der Adresse 0 aussieht, und die zweiten bei 4: das ist eine Tabelle der Handler aufgerufen, die IVT , und jeder Eintrag hat 4 Bytes.

Minimal Beispiel, das einige IO tut zu Handler sichtbar machen.

Minimal geschütztes Modus Beispiel

Moderne Betriebssysteme laufen im sogenannten geschützten Modus.

Die Handhabung mehr Optionen in diesem Modus hat, so ist es komplizierter, aber der Geist ist das gleiche.

Der Schlüsselschritt ist die LGDT und LIDT Anleitung, die die Adresse einer im Speicher befindlichen Datenstruktur (die Interrupt Descriptor Table) hinweist, dass die Behandlungsroutinen beschrieben.

Minimal Beispiel

Der "int" Befehl bewirkt eine Unterbrechung.

Was ist ein Interrupt?

Einfache Antwort: Eine Unterbrechung, einfach ausgedrückt, ist ein Ereignis, das die CPU unterbricht, und sagt ihm, um eine bestimmte Aufgabe auszuführen

.

Detaillierte Antwort :

Die CPU hat eine Tabelle der Interrupt-Service-Routinen (oder ISR) im Speicher abgelegt. In Real (16 Bit) Modus wird diese gespeichert, wie die IVT oder I nterrupt V ector T imstande. Die IVT wird typischerweise bei 0x0000:0x0000 (physikalische Adresse 0x00000) gelegen, und es ist eine Reihe von segment Offset-Adressen, die zu den ISRs zeigen. Das Betriebssystem kann die bereits bestehenden IVT Einträge mit eigenen ISRs ersetzen.

(Hinweis: Die Größe des IVT 1024 festgelegt ist (0x400) Bytes.)

In Protected (32-Bit) Modus verwendet die CPU einen IDT. Der IDT ist eine Struktur variabler Länge, die Deskriptoren von besteht (sonst als Gates bezeichnet), der die CPU über die Interrupt-Handler sagen. Die Struktur dieser Deskriptoren ist viel komplexer als die IVT einfache segmentOffsetEinträge; hier ist sie:

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

* Die IDT kann von variabler Größe sein, aber es muss sequentiell sein, das heißt, wenn Sie Ihre IDT deklarieren von 0x00 bis 0x50 zu sein, müssen Sie jeder von 0x00 bis 0x50 brechen müssen. Das Betriebssystem muss nicht unbedingt alle von ihnen, so dass die vorliegenden Bit mit der CPU ermöglicht richtig zu handhaben das Betriebssystem unterbricht nicht behandeln will.

Wenn ein Interrupt auftritt (entweder durch einen externen Trigger (beispielsweise ein Hardware-Gerät) in einem IRQ oder durch den int Befehl von einem Programm), schiebt die CPU EFLAGS, CS dann, und dann EIP. (Wird diese automatisch durch iret gestellt, der Interrupt-Rückkehrbefehl.) Das Betriebssystem speichert in der Regel mehr Informationen über den Zustand der Maschine übernimmt die Interrupt, stellt den Maschinenzustand, und weiter auf.

In vielen * NIX OSes (einschließlich Linux), Systemaufrufe Interrupt basiert. Das Programm stellt die Argumente für den Systemaufruf in den Registern (EAX, EBX, ECX, EDX, etc ..), und Anrufe unterbrechen 0x80. Der Kern hat bereits den IDT gesetzt einen Interrupt-Handler auf 0x80 enthalten, die aufgerufen wird, wenn es unterbrechen 0x80 empfängt. Der Kernel liest dann die Argumente und ruft eine Kernfunktion entsprechend. Es kann speichern, eine Rückkehr in EAX / EBX. Systemaufrufe werden weitgehend durch die sysenter und sysexit (oder syscall und sysret auf AMD) Anweisungen ersetzt, die in 0-Ring für eine schnellere Eingabe ermöglichen.

Diese Unterbrechung könnte eine andere Bedeutung in einem anderen Betriebssystem hat. Achten Sie darauf, seine Dokumentation zu überprüfen.

Wie bereits erwähnt, führen sie die Kontrolle springen Vektor 0x80 zu unterbrechen. In der Praxis, was das bedeutet (zumindest unter Linux) besteht darin, dass ein Systemaufruf aufgerufen wird; der genaue Systemaufruf und Argumente werden durch die Inhalte der Register definiert. Zum Beispiel exit () kann durch das Setzen% eax auf 1, gefolgt von 'int 0x80'.

aufgerufen werden

Es erzählt die CPU-Interrupt-Vektor 0x80, zu aktivieren, die auf Linux-Betriebssystemen ist das System-Call-Interrupt verwendet aufzurufen Systemfunktionen wie open() für Dateien und so weiter.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top