Apa arti "int 0x80" dalam kode assembly?


Jawaban:


70

Ini melewati kontrol untuk mengganggu vektor 0x80

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

Di Linux, lihat ini : ini digunakan untuk menangani system_call. Tentu saja di OS lain ini bisa berarti sesuatu yang sama sekali berbeda.


5
Dengan mempersingkat cerita panjang itulah instruksi berarti LAKUKAN untuk instruksi sebelumnya.
Yuda Prawira

2
@YudaPrawira: Anda harus memikirkan instruksi sebelumnya sebagai pengaturan args di register, dan int 0x80sebagai jenis khusus dari callfungsi di kernel (dipilih oleh eax).
Peter Cordes

Mengapa Anda mengatakan "SUDAH digunakan?" Apakah itu tidak digunakan lagi?
Liga

131

intberarti interupsi, dan nomor tersebut 0x80adalah nomor interupsi. Interupsi mentransfer aliran program ke siapa pun yang menangani interupsi tersebut, yang 0x80dalam kasus ini interupsi . Di Linux, 0x80interrupt handler adalah kernel, dan digunakan untuk membuat panggilan sistem ke kernel oleh program lain.

Kernel diberitahu tentang pemanggilan sistem mana yang ingin dibuat oleh program, dengan memeriksa nilai dalam register %eax(sintaks AT&T, dan EAX dalam sintaks Intel). Setiap panggilan sistem memiliki persyaratan berbeda tentang penggunaan register lainnya. Misalnya, nilai 1in %eaxberarti pemanggilan sistem exit(), dan nilai in %ebxmenyimpan nilai kode status untuk exit().


47

Ingatlah bahwa 0x80= 80h=128

Anda dapat melihat di sini bahwa INThanya salah satu dari banyak instruksi (sebenarnya representasi Bahasa Assembly (atau harus saya katakan 'mnemonic') darinya) yang ada di set instruksi x86. Anda juga dapat menemukan informasi lebih lanjut tentang instruksi ini di manual Intel yang ditemukan di sini .

Untuk meringkas dari PDF:

INT n / INTO / INT 3 — Prosedur Panggilan untuk Menyela

Instruksi INT n menghasilkan panggilan ke interupsi atau penangan pengecualian yang ditentukan dengan operan tujuan. Operand tujuan menentukan vektor dari 0 sampai 255, dikodekan sebagai nilai antara 8-bit unsigned. Instruksi INT n adalah mnemonik umum untuk menjalankan panggilan yang dihasilkan perangkat lunak ke pengendali interupsi.

Seperti yang Anda lihat, 0x80 adalah operan tujuan dalam pertanyaan Anda. Pada titik ini CPU mengetahui bahwa ia harus mengeksekusi beberapa kode yang ada di Kernel, tetapi kode apa? Itu ditentukan oleh Vektor Interupsi di Linux.

Salah satu interupsi perangkat lunak DOS yang paling berguna adalah interupsi 0x21. Dengan memanggilnya dengan parameter yang berbeda di register (kebanyakan ah dan al) Anda dapat mengakses berbagai operasi IO, keluaran string dan banyak lagi.

Sebagian besar sistem Unix dan turunannya tidak menggunakan interupsi perangkat lunak, dengan pengecualian interupsi 0x80, yang digunakan untuk melakukan panggilan sistem. Ini dilakukan dengan memasukkan nilai 32-bit yang sesuai dengan fungsi kernel ke dalam register EAX prosesor dan kemudian menjalankan INT 0x80.

Silakan lihat ini, di mana nilai lain yang tersedia di tabel penangan interupsi ditampilkan:

masukkan deskripsi gambar di sini

Seperti yang Anda lihat, tabel menunjukkan CPU untuk menjalankan panggilan sistem. Anda dapat menemukan tabel Panggilan Sistem Linux di sini .

Jadi dengan memindahkan nilai 0x1 ke register EAX dan memanggil INT 0x80 di program Anda, Anda dapat membuat proses pergi menjalankan kode di Kernel yang akan menghentikan (keluar) proses yang sedang berjalan (di Linux, x86 Intel CPU).

Interupsi perangkat keras tidak boleh disamakan dengan interupsi perangkat lunak. Inilah jawaban yang sangat bagus tentang hal ini.

Ini juga merupakan sumber yang bagus.


4
Tautan tabel Panggilan Sistem Linux rusak = \
Miguel Angelo

1
Kebanyakan sistem dan turunan Unix tidak menggunakan interupsi perangkat lunak (kecuali int 0x80) sepertinya cara yang aneh untuk menjelaskannya. Sistem int 0x80Linux i386 memanggil ABI sangat mirip dengan int 0x21ABI DOS . Masukkan nomor panggilan di register (AH untuk DOS, EAX untuk Linux), dan arg lainnya di register lain, kemudian jalankan instruksi interupsi perangkat lunak. Perbedaan utama adalah pada apa yang diizinkan oleh system call (mengakses perangkat keras secara langsung di DOS tetapi tidak di Linux), bukan pada cara Anda memanggilnya.
Peter Cordes

Berikut adalah tautan tabel syscall yang tidak rusak. syscalls.kernelgrok.com Perluas saja untuk menampilkan semua panggilan di bagian atas.
ollien

Saat menggunakan linux 64bits, Anda dapat melihat panggilan sistem tersedia di/usr/include/x86_64-linux-gnu/asm/unistd_64.h
ton

12

Contoh panggilan sistem Linux minimal yang dapat dijalankan

Linux menyiapkan pengendali interupsi 0x80sedemikian rupa sehingga ia mengimplementasikan panggilan sistem, sebuah cara bagi program-program userland untuk berkomunikasi dengan kernel.

.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

Kompilasi dan jalankan dengan:

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

Hasil: program mencetak ke stdout:

hello world

dan keluar dengan bersih.

Anda tidak dapat mengatur penangan interupsi Anda sendiri langsung dari userland karena Anda hanya memiliki ring 3 dan Linux mencegah Anda melakukannya .

GitHub upstream . Diuji di Ubuntu 16.04.

Alternatif yang lebih baik

int 0x80telah digantikan oleh alternatif yang lebih baik untuk melakukan panggilan sistem: pertama sysenter, kemudian VDSO.

x86_64 memiliki instruksi barusyscall .

Lihat juga: Apa yang lebih baik "int 0x80" atau "syscall"?

Contoh minimal 16-bit

Pertama pelajari cara membuat OS bootloader minimal dan menjalankannya di QEMU dan perangkat keras nyata seperti yang telah saya jelaskan di sini: https://stackoverflow.com/a/32483545/895245

Sekarang Anda dapat menjalankan mode real 16-bit:

    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

Ini akan dilakukan secara berurutan:

  • Do 0.
  • Do 1.
  • hlt: berhenti mengeksekusi

Perhatikan bagaimana prosesor mencari penangan pertama di alamat 0, dan yang kedua di 4: itu adalah tabel penangan yang disebut IVT , dan setiap entri memiliki 4 byte.

Contoh minimal yang melakukan beberapa IO untuk membuat penangan terlihat.

Contoh mode perlindungan minimal

Sistem operasi modern berjalan dalam apa yang disebut mode terlindungi.

Penanganannya memiliki lebih banyak opsi dalam mode ini, jadi lebih kompleks, tetapi semangatnya sama.

Langkah kuncinya adalah menggunakan instruksi LGDT dan LIDT, yang menunjukkan alamat struktur data dalam memori (Tabel Descriptor Interupsi) yang menjelaskan penangan.

Contoh minimal



4

Instruksi "int" menyebabkan interupsi.

Apa itu interupsi?

Jawaban Sederhana: Sebuah interupsi, sederhananya, adalah peristiwa yang mengganggu CPU, dan menyuruhnya untuk menjalankan tugas tertentu.

Jawaban Rinci :

CPU memiliki tabel Interrupt Service Routines (atau ISRs) yang disimpan di memori. Dalam Real Mode (16-bit), ini disimpan sebagai IVT , atau saya nterrupt V ektor T mampu. IVT biasanya terletak di 0x0000:0x0000(alamat fisik 0x00000), dan merupakan rangkaian alamat offset segmen yang mengarah ke ISR. OS dapat mengganti entri IVT yang sudah ada dengan ISR-nya sendiri.

(Catatan: Ukuran IVT ditetapkan pada 1024 (0x400) byte.)

Dalam Mode Terproteksi (32-bit), CPU menggunakan IDT. IDT adalah struktur dengan panjang variabel yang terdiri dari deskriptor (atau dikenal sebagai gerbang), yang memberi tahu CPU tentang penangan interupsi. Struktur deskriptor ini jauh lebih kompleks daripada entri offset segmen sederhana IVT; ini dia:

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 mungkin berukuran variabel, tetapi harus berurutan, yaitu jika Anda mendeklarasikan IDT Anda dari 0x00 hingga 0x50, Anda harus memiliki setiap interupsi dari 0x00 hingga 0x50. OS tidak selalu menggunakan semuanya, jadi bit Present memungkinkan CPU untuk menangani interupsi yang tidak ingin ditangani OS.

Ketika interupsi terjadi (baik oleh pemicu eksternal (misalnya perangkat keras) di IRQ, atau dengan intinstruksi dari program), CPU mendorong EFLAGS, lalu CS, dan kemudian EIP. (Ini secara otomatis dipulihkan oleh iret, instruksi pengembalian interupsi.) OS biasanya menyimpan lebih banyak informasi tentang status mesin, menangani interupsi, memulihkan status mesin, dan melanjutkan.

Di banyak * NIX OS (termasuk Linux), panggilan sistem berbasis interupsi. Program ini menempatkan argumen ke panggilan sistem di register (EAX, EBX, ECX, EDX, dll ..), dan panggilan interupsi 0x80. Kernel telah menetapkan IDT untuk memuat penangan interupsi pada 0x80, yang dipanggil ketika menerima interupsi 0x80. Kernel kemudian membaca argumen dan menjalankan fungsi kernel yang sesuai. Ini mungkin menyimpan pengembalian dalam EAX / EBX. Panggilan sistem sebagian besar telah digantikan oleh sysenterdan sysexit(atau syscalldansysret instruksi pada AMD), yang memungkinkan untuk masuk lebih cepat ke ring 0.

Interupsi ini bisa memiliki arti berbeda di OS yang berbeda. Pastikan untuk memeriksa dokumentasinya.


Fakta menarik: Panggilan sistem i386 FreeBSD, ABI, meneruskan argumen pada tumpukan ruang pengguna. Hanya eaxdigunakan untuk nomor syscall. asm.sourceforge.net/intro/hello.html
Peter Cordes

2

Seperti disebutkan, itu menyebabkan kontrol melompat ke vektor interupsi 0x80. Dalam praktiknya, ini berarti (setidaknya di Linux) adalah bahwa panggilan sistem dipanggil; panggilan sistem dan argumen yang tepat ditentukan oleh konten register. Misalnya, exit () bisa dipanggil dengan menyetel% eax ke 1 diikuti dengan 'int 0x80'.


1

Ini memberitahu cpu untuk mengaktifkan vektor interupsi 0x80, yang pada OS Linux adalah interupsi panggilan sistem, digunakan untuk menjalankan fungsi sistem seperti open()untuk file, dan sebagainya.


9
Sebenarnya, ini tidak memberi tahu kernel ... Ini memberi tahu CPU, yang mencari penangan di IDT, yang akhirnya menjadi penunjuk ke beberapa kode kernel.
asveikau

Benar. Saya kira ungkapan yang lebih baik akan memberitahu CPU untuk mengaktifkan vektor, dan vektor (sebagai bagian dari kernel) memanggil fungsinya.
Amber

yang akhirnya melakukan ini, yang akhirnya melakukan itu, yang kemudian melakukan ini, yang kemudian pergi ke sana dengan bingung . : / Amber punya jawaban yang bisa dimengerti..yaitu ..
Afzaal Ahmad Zeeshan

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.