Ce înseamnă „int 0x80” în codul assembly? (Programare, Asamblare, X86)

Josh Curren a intrebat.

Poate cineva să explice ce face următorul cod de asamblare?

 int 0x80  

Comentarii

9 răspunsuri
jldupont

Trece controlul la vectorul de întrerupere 0x80

Consultați http://en.wikipedia.org/wiki/Interrupt_vector

Pe Linux, aruncați o privire la acest: a fost folosit pentru a gestiona system_call. Desigur, pe un alt sistem de operare, acest lucru ar putea însemna ceva total diferit.

Comentarii

  • prin scurtarea unei povești lungi, instrucțiunile înseamnă că DO IT pentru instrucțiuni a fost înainte. –  > Por Yuda Prawira.
  • @YudaPrawira: ar trebui să vă gândiți la instrucțiunile anterioare ca la configurarea arginților în registre, iar int 0x80 ca un tip special de instrucțiune call către o funcție din nucleu (selectată prin eax). –  > Por Peter Cordes.
  • De ce ați spus „a fost folosit”? Nu mai este folosit? –  > Por Liga.
Polat Tuzla

int înseamnă întrerupere, iar numărul 0x80 este numărul întreruperii.O întrerupere transferă fluxul programului către cel care gestionează acea întrerupere, care este întreruperea 0x80 în acest caz. În Linux, 0x80 gestionarul de întreruperi este kernelul și este utilizat pentru a efectua apeluri de sistem către kernel de către alte programe.

Kernelul este notificat cu privire la apelul de sistem pe care programul dorește să îl facă, prin examinarea valorii din registrul %eax (sintaxa AT&T și EAX în sintaxa Intel). Fiecare apel de sistem are cerințe diferite în ceea ce privește utilizarea celorlalte registre. De exemplu, o valoare de 1 în %eax înseamnă un apel de sistem de exit(), , iar valoarea în %ebx deține valoarea codului de stare pentru exit().

Koray Tugay

Rețineți că 0x80 = 80h = 128

Puteți vedea aiciINT este doar una dintre multele instrucțiuni (de fapt, reprezentarea în limbaj de asamblare (sau ar trebui să spun „mnemotehnică”) a acesteia) care există în setul de instrucțiuni x86. Puteți găsi mai multe informații despre această instrucțiune și în manualul propriu al Intel care se găsește aici.

Ca să rezumăm din PDF:

INT n/INTO/INT 3-Apel la procedura de întrerupere

Instrucțiunea INT n generează un apel la operatorul de întrerupere sau de gestionare a excepțiilor specificat cu operandul de destinație. Operandul de destinație specifică un vector de la 0 la 255, codificat ca o valoare intermediară nesemnată pe 8 biți. Instrucțiunea INT n este mnemotehnica generală pentru a executa un apel generat de software la un gestionar de întreruperi.

După cum se poate observa 0x80 este operand de destinație în întrebarea dumneavoastră. În acest moment, procesorul știe că trebuie să execute un cod care se află în Kernel, dar ce cod? Acest lucru este determinat de Vectorul de întrerupere din Linux.

Una dintre cele mai utile întreruperi software DOS a fost întreruperea 0x21. Prin apelarea acestuia cu diferiți parametri în registre (în principal ah și al) se putea accesa diverse operațiuni IO, ieșire de șiruri de caractere și multe altele.

Cele mai multe sisteme Unix și derivate nu folosesc întreruperi software, cu excepția întreruperii 0x80, utilizată pentru a efectua apeluri de sistem. Acest lucru se realizează prin introducerea unui valoare pe 32 de biți corespunzătoare unei funcții de kernel în registrul EAX al procesorului și apoi executând INT 0x80.

Aruncați o privire la acest vă rog unde sunt prezentate alte valori disponibile în tabelele de gestionare a întreruperilor:

După cum puteți vedea, tabelul indică procesorului să execute un apel de sistem. Puteți găsi tabelul Linux System Call (apel de sistem) aici.

Astfel, prin mutarea valorii 0x1 în registrul EAX și apelarea INT 0x80 în programul dumneavoastră, puteți face ca procesul să execute codul din Kernel care va opri (ieși) procesul curent în curs de execuție (pe Linux, x86 Intel CPU).

O întrerupere hardware nu trebuie confundată cu o întrerupere software. Iată un răspuns foarte bun în această privință.

Acest este, de asemenea, o sursă bună.

Comentarii

  • Legătura cu tabelul Linux System Call este ruptă = –  > Por Miguel Angelo.
  • Majoritatea sistemelor Unix și derivate nu folosesc întreruperi software (cu excepția int 0x80) pare un mod ciudat de a spune asta. int 0x80 i386 Linux system call ABI este extrem de asemănător cu cel al DOS int 0x21 ABI. Se pune un număr de apel într-un registru (AH pentru DOS, EAX pentru Linux) și alte argumente în alte registre, apoi se execută o instrucțiune de întrerupere software. Principala diferență constă în ceea ce vă permit să faceți apelurile de sistem (accesați hardware-ul direct în DOS, dar nu și în Linux), nu în modul în care le apelați. –  > Por Peter Cordes.
  • Iată un link către un tabel de syscall-uri care nu este rupt. syscalls.kernelgrok.com Doar extindeți-l pentru a afișa toate apelurile în partea de sus. –  > Por ollien.
  • Atunci când utilizați linux 64bits, puteți vedea apelul de sistem disponibil la /usr/include/x86_64-linux-gnu/asm/unistd_64.h –  > Por ton.
Ciro Santilli新疆棉花TRUMP BAN BAD

Exemplu minim de apel de sistem Linux executabil

Linux setează gestionarul de întreruperi pentru 0x80 astfel încât să implementeze apelurile de sistem, o modalitate de comunicare a programelor userland cu kernelul.

.data
    s:
        .ascii "hello world
"
        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

Compilați și rulați cu:

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

Rezultat: programul tipărește în stdout:

hello world

și iese curat.

Nu vă puteți seta proprii gestionari de întreruperi direct din userland, deoarece aveți doar inelul 3 și Linux vă împiedică să faceți acest lucru.

GitHub upstream. Testat pe Ubuntu 16.04.

Alternative mai bune

int 0x80 a fost înlocuită de alternative mai bune pentru a face apeluri de sistem: în primul rând sysenter, , apoi VDSO.

x86_64 are un nou syscall instrucțiune.

A se vedea, de asemenea: Ce este mai bine „int 0x80” sau „syscall”?

Exemplu minim pe 16 biți

Mai întâi învățați cum să creați un sistem de operare minim de bootloader și să îl rulați pe QEMU și hardware real, așa cum am explicat aici: https://stackoverflow.com/a/32483545/895245

Acum puteți rula în modul real pe 16 biți:

    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

Acest lucru s-ar face în ordine:

  • Do 0.
  • Do 1.
  • hlt: opriți execuția

Observați cum procesorul caută primul handler la adresa 0, , iar al doilea la 4: acesta este un tabel de gestionari numit IVT, , iar fiecare intrare are 4 octeți.

Exemplu minimalist care efectuează câteva IO pentru a face vizibili handlerii.

Exemplu minim de mod protejat

Sistemele de operare moderne rulează în așa-numitul mod protejat.

Manipularea are mai multe opțiuni în acest mod, deci este mai complexă, dar spiritul este același.

Pasul cheie constă în utilizarea instrucțiunilor LGDT și LIDT, care indică adresa unei structuri de date în memorie (Interrupt Descriptor Table) care descrie gestionarii.

Exemplu minimalist

Tom

int 0x80 este instrucțiunea în limbaj de asamblare care este utilizată pentru a invoca apelurile de sistem în Linux pe procesoarele x86 (adică, compatibile cu Intel).

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

adrian

Instrucțiunea „int” provoacă o întrerupere.

Ce este o întrerupere?

Răspuns simplu: O întrerupere este, pur și simplu, un eveniment care întrerupe procesorul și îi spune acestuia să execute o anumită sarcină.

Răspuns detaliat:

Procesorul dispune de un tabel de rutine de serviciu de întrerupere (sau ISR) stocate în memorie. În modul real (16 biți), aceasta este stocată sub forma de IVT, , sau Interrupt Vector Table. IVT se află de obicei la 0x0000:0x0000 (adresa fizică 0x00000) și este o serie de adrese cu decalaj de segment care indică ISR-urile. Sistemul de operare poate înlocui intrările IVT preexistente cu propriile sale ISR.

(Notă: dimensiunea IVT este fixată la 1024 (0x400) octeți).

În modul protejat (32 de biți), procesorul utilizează un IDT. IDT este o structură de lungime variabilă care constă din descriptori (cunoscuți și sub numele de porți), care informează CPU despre gestionarii de întreruperi. Structura acestor descriptori este mult mai complexă decât simplele intrări segment-offset ale IVT; iată-o:

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 poate fi de mărime variabilă, dar trebuie să fie secvențial, adică dacă declarați că IDT-ul este de la 0x00 la 0x50, trebuie să aveți fiecare întrerupere de la 0x00 la 0x50. Sistemul de operare nu le folosește neapărat pe toate, astfel încât bitul Present permite procesorului să gestioneze în mod corespunzător întreruperile pe care sistemul de operare nu intenționează să le gestioneze.

Atunci când apare o întrerupere (fie printr-un declanșator extern (de exemplu, un dispozitiv hardware) într-un IRQ, fie de către int instrucțiunea unui program), CPU împinge EFLAGS, apoi CS și apoi EIP. (Acestea sunt restabilite automat de către iret, , instrucțiunea de întoarcere a întreruperii). De obicei, sistemul de operare stochează mai multe informații despre starea mașinii, gestionează întreruperea, restabilește starea mașinii și continuă.

În multe sisteme de operare *NIX (inclusiv Linux), apelurile de sistem se bazează pe întreruperi. Programul plasează argumentele apelului de sistem în registre (EAX, EBX, ECX, EDX, etc.) și apelează întreruperea 0x80. Kernelul a setat deja IDT pentru a conține un gestionar de întreruperi pe 0x80, care este apelat atunci când primește întreruperea 0x80. Kernelul citește apoi argumentele și invocă o funcție a kernelului în mod corespunzător. Acesta poate stoca un retur în EAX/EBX. Apelurile de sistem au fost în mare parte înlocuite de către sysenter și sysexit (sau syscall și sysret pe AMD), care permit o intrare mai rapidă în inelul 0.

Această întrerupere ar putea avea o semnificație diferită într-un sistem de operare diferit. Asigurați-vă că verificați documentația acestuia.

Comentarii

  • Fapt amuzant: ABI-ul apelului de sistem i386 al FreeBSD trece arginții pe stiva din spațiul utilizatorului. Numai eax este utilizat pentru numărul de apel de sistem. asm.sourceforge.net/intro/hello.html –  > Por Peter Cordes.
Steve Smith

După cum s-a menționat, aceasta determină controlul să sară la vectorul de întrerupere 0x80. În practică, ceea ce înseamnă (cel puțin sub Linux) este că este invocat un apel de sistem; apelul de sistem exact și argumentele sunt definite de conținutul registrelor. De exemplu, exit() poate fi invocat prin setarea lui %eax la 1, urmată de „int 0x80”.

Amber

Aceasta îi spune calculatorului să activeze vectorul de întrerupere 0x80, care pe sistemele de operare Linux este întreruperea apelului de sistem, utilizat pentru a invoca funcții de sistem precum open() pentru fișiere, etc.

Comentarii

  • Strict vorbind, nu îi spune kernelului… Îi spune procesorului, care caută gestionarul în IDT, care sfârșește prin a fi un pointer către un cod kernel. –  > Por asveikau.
  • Adevărat. Presupun că o formulare mai bună ar fi că îi spune procesorului să activeze vectorul, iar vectorul (ca parte a nucleului) invocă funcția. –  > Por Amber.
  • care sfârșește prin a face asta, care la rândul ei sfârșește prin a face asta, care apoi face asta, care apoi merge acolo confuz:/ Amber are un răspuns care este de înțeles..asta e.. –  > Por Afzaal Ahmad Zeeshan.
Praveen Kumar Karthikeyan

int nu este altceva decât o întrerupere, adică procesorul își va pune în așteptare execuția curentă.

0x80 nu este altceva decât un apel de sistem sau un apel de kernel.adică funcția de sistem va fi executată.

Pentru a fi mai exact, 0x80 reprezintă rt_sigtimedwait/init_module/restart_sys variază de la o arhitectură la alta.

Pentru mai multe detalii, consultațihttps://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md