"İnt 0x80" derleme kodunda ne anlama geliyor?


Yanıtlar:


70

0x80 vektörünü kesmek için kontrolden geçer

Bkz. Http://en.wikipedia.org/wiki/Interrupt_vector

Linux'ta, bir göz bu : o işlemek için kullanıldı system_call. Elbette başka bir işletim sisteminde bu tamamen farklı bir anlama gelebilir.


5
kısaltmak uzun hikaye bu talimatlar daha önce talimat için DO IT anlamına gelir .
Yuda Prawira

2
@YudaPrawira: Önceki talimatları yazmaçlarda argümanlar oluşturmak ve çekirdekteki (tarafından seçilen ) bir işlevin int 0x80özel bir türü olarak düşünmelisiniz . calleax
Peter Cordes

Neden "kullanıldı" dedin? Artık kullanılmıyor mu?
Liga

131

intkesme anlamına gelir ve sayı 0x80, kesme numarasıdır. Bir kesme, program akışını bu kesmeyi işleyen kişiye aktarır, 0x80bu durumda bu kesintidir . Linux'ta, 0x80kesme işleyicisi çekirdektir ve diğer programlar tarafından çekirdeğe sistem çağrıları yapmak için kullanılır.

Çekirdek, kayıttaki değer incelenerek programın hangi sistem çağrısını yapmak istediği konusunda bilgilendirilir %eax(AT&T sözdizimi ve Intel sözdiziminde EAX). Her sistem çağrısının diğer kayıtların kullanımıyla ilgili farklı gereksinimleri vardır. Örneğin, 1in değeri %eaxbir sistem çağrısı anlamına gelir exit()ve içindeki değer %ebxiçin durum kodunun değerini tutar exit().


47

Unutmayın 0x80= 80h=128

Burada bunun INTx86 komut setinde bulunan birçok talimattan (aslında Assembly Dili gösterimi (veya 'anımsatıcı' demeliyim)) sadece biri olduğunu görebilirsiniz . Bu talimat hakkında daha fazla bilgiyi burada bulunan Intel'in kendi kılavuzunda da bulabilirsiniz .

PDF'den özetlemek için:

INT n / INTO / INT 3 - İşlemi Kesmek İçin Çağrı

INT n komutu, hedef işlenen ile belirtilen kesme veya istisna işleyicisine bir çağrı üretir. Hedef işlenen, 8 bitlik işaretsiz ara değer olarak kodlanmış, 0 ile 255 arasında bir vektör belirtir. INT n komutu, bir kesme işleyicisine yazılım tarafından üretilen bir çağrıyı yürütmek için genel bir anımsatıcıdır.

Gördüğünüz gibi 0x80 , hedef işlenen sorunuzdaki . Bu noktada CPU, Çekirdekte bulunan bazı kodları yürütmesi gerektiğini bilir, ancak hangi kod? Bu, Linux'taki Kesme Vektörü tarafından belirlenir.

En kullanışlı DOS yazılım kesintilerinden biri 0x21 kesintisiydi. Kayıtlarda (çoğunlukla ah ve al) farklı parametrelerle çağırarak çeşitli IO işlemlerine, dizgi çıkışına ve daha fazlasına erişebilirsiniz.

Çoğu Unix sistemi ve türevi, sistem çağrıları yapmak için kullanılan 0x80 kesintisi dışında yazılım kesintilerini kullanmaz. Bu, işlemcinin EAX yazmacına bir çekirdek işlevine karşılık gelen 32 bitlik bir değer girilerek ve ardından INT 0x80 çalıştırılarak gerçekleştirilir.

Lütfen kesme işleyici tablolarındaki diğer mevcut değerlerin gösterildiği şuna bir göz atın:

görüntü açıklamasını buraya girin

Gördüğünüz gibi, tablo CPU'nun bir sistem çağrısı yürütmesini işaret ediyor. Linux Sistem Çağrısı tablosunu burada bulabilirsiniz .

Bu nedenle, 0x1 değerini EAX kaydına taşıyarak ve programınızda INT 0x80'i çağırarak, sürecin devam eden kodu Çekirdekte yürütmesini sağlayabilirsiniz, bu da geçerli çalışan işlemi durdurur (Linux'ta, x86 Intel CPU'da).

Bir donanım kesintisi, bir yazılım kesintisi ile karıştırılmamalıdır. Buraya bu konuda çok güzel bir cevap.

Bu da iyi bir kaynaktır.


4
Linux Sistem Çağrısı tablosu bağlantısı bozuk = \
Miguel Angelo

1
Çoğu Unix sistemi ve türevi yazılım kesintilerini kullanmaz (int 0x80 hariç) , bunu ifade etmenin garip bir yolu gibi görünüyor. int 0x80İ386 Linux sistem çağrısı ABI DOS son derece benzerdir int 0x21ABI. Bir kayda bir çağrı numarası (DOS için AH, Linux için EAX) ve diğer kayıtlara diğer argümanlar koyun, ardından bir yazılım kesme talimatı çalıştırın. Temel fark, sistem çağrılarının size nasıl izin verdiğidir (donanıma doğrudan DOS'ta erişir, ancak Linux'ta değil), onları nasıl çağırdığınızla değil.
Peter Cordes

İşte bozuk olmayan bir sistem çağrısı tablosu bağlantısı. syscalls.kernelgrok.com Sadece tüm aramaları en üstte gösterecek şekilde genişletin.
ollien

Linux 64bits kullanırken, sistem çağrısının /usr/include/x86_64-linux-gnu/asm/unistd_64.h
tonda

12

Minimum çalıştırılabilir Linux sistem çağrısı örneği

Linux 0x80, kullanıcı alanındaki programların çekirdekle iletişim kurması için bir yol olan sistem çağrılarını uygulayacak şekilde kesme işleyicisini ayarlar .

.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

Aşağıdakilerle derleyin ve çalıştırın:

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

Sonuç: program stdout'a yazdırır:

hello world

ve temiz bir şekilde çıkar.

Kendi kesme işleyicilerinizi doğrudan kullanıcı bölgesinden ayarlayamazsınız çünkü yalnızca ring 3'e sahipsiniz ve Linux bunu yapmanızı engelliyor .

GitHub yukarı akış . Ubuntu 16.04'te test edilmiştir.

Daha iyi alternatifler

int 0x80yerini sistem çağrıları yapmak için daha iyi alternatifler almıştır: önce sysenter, sonra VDSO.

x86_64 yeni bir syscalltalimat içeriyor .

Ayrıca bkz: "int 0x80" veya "syscall" daha iyi nedir?

Minimum 16 bit örnek

Öncelikle minimal bir önyükleyici işletim sisteminin nasıl oluşturulacağını ve burada açıkladığım gibi QEMU ve gerçek donanım üzerinde nasıl çalıştırılacağını öğrenin: https://stackoverflow.com/a/32483545/895245

Artık 16 bit gerçek modda çalıştırabilirsiniz:

    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

Bu sırayla yapacaktı:

  • Do 0.
  • Do 1.
  • hlt: yürütmeyi durdur

İşlemcinin adreste ilk işleyiciyi nasıl aradığına ve 0ikincisini 4: bu IVT adı verilen bir işleyiciler tablosudur ve her girişin 4 baytı vardır.

Biraz IO yapan minimal örnek görünür kılmak için yapan

Minimum korumalı mod örneği

Modern işletim sistemleri sözde korumalı modda çalışır.

Bu modda kullanım daha fazla seçeneğe sahiptir, bu nedenle daha karmaşıktır, ancak ruhu aynıdır.

Anahtar adım, işleyicileri tanımlayan bir bellek içi veri yapısının (Kesme Tanımlayıcı Tablosu) adresini işaret eden LGDT ve LIDT talimatlarını kullanmaktır.

Minimal örnek



4

"İnt" komutu bir kesmeye neden olur.

Kesinti nedir?

Basit Cevap: Basitçe ifade etmek gerekirse, kesme, CPU'yu kesintiye uğratan ve ona belirli bir görevi çalıştırmasını söyleyen bir olaydır.

Ayrıntılı Cevap :

CPU, bellekte depolanan bir Kesme Servis Rutinleri (veya ISR'ler) tablosuna sahiptir. Real, (16-bit) Modunda, bu şekilde depolanan IVT veya bir nterrupt V ector T mümkün. IVT tipik olarak 0x0000:0x0000(fiziksel adres 0x00000) konumunda bulunur ve ISR'leri işaret eden bir dizi segment ofset adresidir . İşletim sistemi, önceden var olan IVT girişlerini kendi ISR'leriyle değiştirebilir.

(Not: IVT'nin boyutu 1024 (0x400) bayta sabitlenmiştir.)

Korumalı (32 bit) Modda, CPU bir IDT kullanır. IDT, CPU'ya kesme işleyicileri hakkında bilgi veren tanımlayıcılardan (kapılar olarak da bilinir) oluşan değişken uzunluklu bir yapıdır . Bu tanımlayıcıların yapısı, IVT'nin basit segment ofset girişlerinden çok daha karmaşıktır; işte burada:

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 değişken boyutta olabilir, ancak sıralı olmalıdır, yani IDT'nizin 0x00 ile 0x50 arasında olduğunu bildirirseniz, 0x00 ile 0x50 arasında her kesmeye sahip olmalısınız. İşletim sistemi bunların hepsini kullanmak zorunda değildir, bu nedenle Sunum biti, CPU'nun işletim sisteminin işlemeyi düşünmediği kesintileri düzgün bir şekilde işlemesine izin verir.

Bir kesinti meydana geldiğinde (bir intIRQ'da harici bir tetikleyici (örneğin bir donanım aygıtı) veya bir programdan gelen talimatla), CPU EFLAGS, ardından CS ve ardından EIP'ye basar. (Bunlar iret, kesme dönüş talimatı tarafından otomatik olarak geri yüklenir .) İşletim sistemi genellikle makinenin durumu hakkında daha fazla bilgi depolar, kesmeyi ele alır, makine durumunu geri yükler ve devam eder.

Birçok * NIX işletim sisteminde (Linux dahil), sistem çağrıları kesintiye dayalıdır. Program kayıtlardaki sistem çağrısına argümanları koyar (EAX, EBX, ECX, EDX, vb.) Ve interrupt 0x80'i çağırır. Çekirdek, IDT'yi 0x80'de bir kesme işleyicisi içerecek şekilde ayarlamıştır; bu, kesme 0x80 aldığında çağrılır. Çekirdek daha sonra argümanları okur ve buna göre bir çekirdek işlevini çağırır. EAX / EBX'te bir iadeyi saklayabilir. Sistem çağrılarının yerini büyük ölçüde sysenterve sysexit(veya syscallvesysret halka 0 içine daha hızlı giriş için izin talimatlar, AMD üzerine).

Bu kesintinin farklı bir işletim sisteminde farklı bir anlamı olabilir. Belgelerini kontrol ettiğinizden emin olun.


Eğlenceli gerçek: FreeBSD'nin i386 sistem çağrısı ABI, kullanıcı alanı yığınındaki değiştirgeleri aktarır. Yalnızca eaxsistem çağrı numarası için kullanılır. asm.sourceforge.net/intro/hello.html
Peter Cordes

2

Belirtildiği gibi, denetimin 0x80 vektörünü kesmek için atlamasına neden olur. Pratikte bunun anlamı (en azından Linux altında) bir sistem çağrısının başlatılmasıdır; tam sistem çağrısı ve argümanlar kayıtların içeriği ile tanımlanır. Örneğin, exit (),% eax olarak 1 ve ardından 'int 0x80' ayarlanarak çağrılabilir.


1

İşlemciye, Linux işletim sistemlerinde open()dosyalar vb. Gibi sistem işlevlerini çağırmak için kullanılan sistem çağrısı kesmesi olan 0x80 kesinti vektörünü etkinleştirmesini söyler .


9
Açıkçası, çekirdeğe söylemez ... IDT'de işleyiciyi arayan CPU'ya söyler ve sonunda bir çekirdek koduna işaretçi olur.
asveikau

Doğru. Sanırım daha iyi ifade, CPU'ya vektörü etkinleştirmesini söyler ve vektör (çekirdeğin parçası olarak) işlevi çağırır.
Amber

bu da bunu yapmakla sonuçlanır, ki bu da bunu yapmakla sonuçlanır, sonra bunu yapar, sonra oraya karışır . : /
Amber'ın

1

int bir kesintiden başka bir şey değildir, yani işlemci mevcut yürütmesini beklemeye alacaktır.

0x80, bir sistem çağrısı veya çekirdek çağrısından başka bir şey değildir. yani sistem işlevi yürütülecektir.

Belirli bir 0x80 olması, rt_sigtimedwait / init_module / restart_sys'i temsil eder, mimariden mimariye değişir.

Daha fazla ayrıntı için https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md adresine bakın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.