Was bedeutet „int 0x80“ bedeutet in Assembler-Code?
Frage
Kann jemand erklären, was der folgende Assembler-Code funktioniert?
int 0x80
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()
.
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önnenDie 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:
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.
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
erstenint 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.
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.