簡體   English   中英

匯編代碼中的“int 0x80”是什么意思?

[英]What does "int 0x80" mean in assembly code?

有人可以解釋以下匯編代碼的作用嗎?

 int 0x80  

int表示中斷,數字0x80是中斷號。 中斷將程序流傳輸給處理該中斷的任何人,在本例中為中斷0x80 在 Linux 中, 0x80中斷處理程序是內核,用於其他程序對內核進行系統調用。

通過檢查寄存器%eax (AT&T 語法和 Intel 語法中的 EAX)中的值,內核被告知程序想要進行哪個系統調用。 每個系統調用對其他寄存器的使用都有不同的要求。 例如, %eax的值1表示exit()的系統調用,而%ebx的值保存exit()的狀態代碼的值。

它將控制權傳遞給中斷向量 0x80

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

在 Linux 上,看看這個:它被用來處理system_call 當然,在另一個操作系統上,這可能意味着完全不同的東西。

請記住, 0x80 = 80h = 128

您可以在這里看到INT只是 x86 指令集中存在的眾多指令之一(實際上是匯編語言表示(或者我應該說它的“助記符”))。 您還可以在此處找到的英特爾自己的手冊中找到有關此指令的更多信息。

從PDF總結:

INT n/INTO/INT 3—調用中斷程序

INT n 指令生成對目標操作數指定的中斷或異常處理程序的調用。 目標操作數指定從 0 到 255 的向量,編碼為 8 位無符號中間值。 INT n 指令是執行軟件生成的中斷處理程序調用的通用助記符。

如您所見, 0x80是您問題中的目標操作數 此時 CPU 知道它應該執行一些駐留在內核中的代碼,但是什么代碼呢? 這是由 Linux 中的中斷向量決定的。

最有用的 DOS 軟件中斷之一是中斷 0x21。 通過在寄存器中使用不同的參數(主要是 ah 和 al)調用它,您可以訪問各種 IO 操作、字符串輸出等。

大多數 Unix 系統及其衍生產品不使用軟件中斷,除了用於進行系統調用的中斷 0x80。 這是通過將與內核函數對應32 位值輸入處理器的 EAX 寄存器然后執行 INT 0x80 來實現的。

請查看中斷處理程序表中其他可用值的位置:

在此處輸入圖片說明

如您所見,該表指向 CPU 執行系統調用。 您可以在此處找到 Linux 系統調用表。

因此,通過將值 0x1 移動到 EAX 寄存器並在您的程序中調用 INT 0x80,您可以讓進程執行內核中的代碼,這將停止(退出)當前正在運行的進程(在 Linux 上,x86 Intel CPU)。

硬件中斷不能與軟件中斷混淆。 是關於這方面的一個很好的答案。

也是很好的來源。

最小的可運行 Linux 系統調用示例

Linux 為0x80設置中斷處理程序,以便它實現系統調用,這是用戶態程序與內核通信的一種方式。

.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

編譯並運行:

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

結果:程序打印到標准輸出:

hello world

並干凈地退出。

您不能直接從用戶空間設置您自己的中斷處理程序,因為您只有ring 3,而 Linux 阻止您這樣做

GitHub 上游. 在 Ubuntu 16.04 上測試。

更好的選擇

int 0x80已被更好的系統調用替代方案取代:首先是sysenter ,然后是 VDSO。

x86_64 有一個新的syscall指令

另請參閱: “int 0x80”或“syscall”哪個更好?

最小 16 位示例

首先學習如何創建一個最小的引導加載程序操作系統並在 QEMU 和真實硬件上運行它,正如我在這里解釋的: https : //stackoverflow.com/a/32483545/895245

現在您可以在 16 位實模式下運行:

    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

這將按順序執行:

  • Do 0.
  • Do 1.
  • hlt : 停止執行

請注意處理器如何在地址0處查找第一個處理程序,在4處查找第二個處理程序:這是一個稱為IVT的處理程序表,每個條目有 4 個字節。

執行一些 IO以使處理程序可見的最小示例

最小保護模式示例

現代操作系統以所謂的保護模式運行。

這種模式的處理有更多的選擇,所以更復雜,但精神是一樣的。

關鍵步驟是使用 LGDT 和 LIDT 指令,它們指向描述處理程序的內存數據結構(中斷描述符表)的地址。

最小的例子

int 0x80 是匯編語言指令,用於在 x86(即 Intel 兼容)處理器上的 Linux 中調用系統調用。

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

“int”指令導致中斷。

什么是中斷?

簡單回答:中斷,簡單地說,就是中斷 CPU 並告訴它運行特定任務的事件。

詳細解答

CPU 有一個存儲在內存中的中斷服務程序(或 ISR)表。 在真實的(16位)的模式下,該被存儲為IVT,nterrupt V厄克托Ť能。 IVT 通常位於0x0000:0x0000 (物理地址0x00000 ),它是一系列指向 ISR 的段偏移地址。 操作系統可以用它自己的 ISR 替換預先存在的 IVT 條目。

(注意:IVT 的大小固定為 1024 (0x400) 字節。)

在保護(32 位)模式下,CPU 使用 IDT。 IDT 是一個由描述符(也稱為門)組成的可變長度結構,它告訴 CPU 有關中斷處理程序的信息。 這些描述符的結構比 IVT 的簡單段偏移條目復雜得多; 這里是:

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 可以是可變大小,但它必須是連續的,即如果你聲明你的 IDT 是從 0x00 到 0x50,你必須有從 0x00 到 0x50 的每個中斷。 OS 不一定使用所有這些,因此 Present 位允許 CPU 正確處理 OS 不打算處理的中斷。

當中斷發生時(通過 IRQ 中的外部觸發器(例如硬件設備),或程序中的int指令),CPU 推送 EFLAGS,然后是 CS,然后是 EIP。 (這些由iret自動恢復,中斷返回指令。)操作系統通常會存儲更多關於機器狀態的信息,處理中斷,恢復機器狀態,然后繼續。

在許多 *NIX 操作系統(包括 Linux)中,系統調用是基於中斷的。 程序將系統調用的參數放入寄存器(EAX、EBX、ECX、EDX 等),並調用中斷 0x80。 內核已經將 IDT 設置為在 0x80 上包含一個中斷處理程序,當它接收到中斷 0x80 時會調用該處理程序。 然后內核讀取參數並相應地調用內核函數。 它可以在 EAX/EBX 中存儲回報。 系統調用在很大程度上被換成了sysentersysexit (或syscallsysret上AMD)指令,允許更快的進入0環。

此中斷在不同的操作系統中可能具有不同的含義。 請務必檢查其文檔。

它告訴 cpu 激活中斷向量 0x80,它在 Linux 操作系統上是系統調用中斷,用於調用系統函數,如文件的open()等。

如前所述,它會導致控制跳轉到中斷向量 0x80。 實際上,這意味着(至少在 Linux 下)是調用系統調用; 確切的系統調用和參數由寄存器的內容定義。 例如,可以通過將 %eax 設置為 1 后跟“int 0x80”來調用 exit()。

int 只是一個中斷,即處理器將暫停其當前執行。

0x80 只不過是一個系統調用或內核調用。 即系統函數將被執行。

具體來說,0x80 代表 rt_sigtimedwait/init_module/restart_sys,它因架構而異。

有關更多詳細信息,請參閱https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM