Що означає “int 0x80” у коді збірки?


Відповіді:


70

Він передає управління вектору переривання 0x80

Див. Http://en.wikipedia.org/wiki/Interrupt_vector

У Linux подивіться на це : він використовувався для обробки system_call. Звичайно, в іншій ОС це може означати щось зовсім інше.


5
скорочуючи довгу історію, це вказівки означають ЗРОБИТИ, щоб інструкція була раніше.
Юда Правіра,

2
@YudaPrawira: ви повинні думати про попередні інструкції як про налаштування аргументів у регістрах і int 0x80як про особливий вид callфункції в ядрі (вибраний eax).
Пітер Кордес,

Чому ви сказали "ВИКОРИСТОВАНО?" Чи більше не використовується?
Ліга

130

intозначає переривання, а число 0x80є числом переривання. Переривання передає потік програми тому, хто обробляє це переривання, яке 0x80в цьому випадку є перериванням . У Linux 0x80обробник переривань є ядром і використовується для здійснення системних викликів до ядра іншими програмами.

Ядро отримує повідомлення про те, який системний виклик хоче зробити програма, перевіряючи значення в реєстрі %eax(синтаксис AT&T та EAX у синтаксисі Intel). Кожен системний виклик має різні вимоги щодо використання інших регістрів. Наприклад, значення 1in %eaxозначає системний виклик exit(), а значення in %ebxмістить значення коду стану для exit().


47

Майте на увазі, що 0x80= 80h=128

Ви можете побачити тут , що INTце тільки один з багатьох інструкцій ( на насправді уявлення асемблера (або я повинен сказати «Мнемоніка») з неї) , яка існує в наборі команд x86. Ви також можете знайти додаткову інформацію про цю інструкцію у власному посібнику Intel, який знаходиться тут .

Підсумовуємо з PDF-файлу:

INT n / INTO / INT 3 — Процедура виклику до переривання

Інструкція INT n генерує виклик обробнику переривання або винятку, вказаному з операндом призначення. Операнд призначення вказує вектор від 0 до 255, кодований як 8-бітове беззнакове проміжне значення. Інструкція INT n є загальною мнемонікою для виконання програмно-генерованого виклику до обробника переривань.

Як бачите, 0x80 - операнд призначення у вашому запитанні. На даний момент центральний процесор знає, що він повинен виконати якийсь код, який знаходиться в ядрі, але який код? Це визначається вектором переривань у Linux.

Одним з найкорисніших програмних переривань DOS було переривання 0x21. Зателефонувавши до нього з різними параметрами в регістрах (переважно ah та al), ви отримаєте доступ до різних операцій вводу-виводу, виводу рядків тощо.

Більшість систем Unix та похідних не використовують програмні переривання, за винятком переривання 0x80, що використовується для здійснення системних дзвінків. Це досягається введенням 32-бітового значення, що відповідає функції ядра, в регістр EAX процесора, а потім виконанням INT 0x80.

Погляньте на це, будь-де, де показані інші доступні значення в таблицях обробників переривань:

введіть тут опис зображення

Як ви можете бачити, таблиця вказує на центральний процесор для виконання системного виклику. Ви можете знайти таблицю системних дзвінків Linux тут .

Отже, перемістивши значення 0x1 до реєстру EAX і викликавши INT 0x80 у вашій програмі, ви можете змусити процес виконати код у ядрі, який зупинить (вийде) поточний запущений процес (на Linux, x86 Intel CPU).

Апаратне переривання не слід плутати з програмним перериванням. Ось дуже гарна відповідь з цього приводу.

Це також є хорошим джерелом.


4
Посилання на таблицю системних викликів Linux не працює = \
Мігель Анджело

1
У більшості систем та похідних Unix не використовуються програмні переривання (крім int 0x80), це виглядає дивним способом. int 0x80I386 Linux системного виклику ABI дуже схожий на DOS int 0x21ABI. Помістіть номер виклику в реєстр (AH для DOS, EAX для Linux) та інші аргументи в інші регістри, а потім запустіть інструкцію переривання програмного забезпечення. Основна відмінність полягає в тому, що дозволяють вам системні виклики (доступ до обладнання безпосередньо в DOS, але не в Linux), а не в тому, як ви їх викликаєте.
Пітер Кордес,

Ось посилання на нерозбиту таблицю syscall. syscalls.kernelgrok.com Просто розгорніть його, щоб показати всі дзвінки вгорі.
ollien

При використанні Linux 64bits, ви можете побачити системний виклик доступного на/usr/include/x86_64-linux-gnu/asm/unistd_64.h
т

13

Приклад мінімального запуску системного виклику 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

Результат: програма друкує до stdout:

hello world

і виходить чисто.

Ви не можете встановити власні обробники переривань безпосередньо з користувацької області, оскільки у вас є лише кільце 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, які вказують адресу структури даних в пам'яті (таблиця дескрипторів переривань), яка описує обробники.

Мінімальний приклад


9

int 0x80 - це інструкція асемблерної мови, яка використовується для виклику системних викликів у Linux на процесорах x86 (тобто сумісних з Intel).

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


4

Інструкція "int" викликає переривання.

Що таке переривання?

Проста відповідь: Простіше кажучи, переривання - це подія, яка перериває центральний процесор і повідомляє йому про те, щоб запустити певне завдання.

Детальна відповідь :

Процесор має таблицю процедур обслуговування переривань (або ISR), що зберігаються в пам'яті. У реальному (16-біт) режимі, це зберігається як IVT , або я nterrupt В Ector Т стані. IVT, як правило, знаходиться за 0x0000:0x0000(фізичною адресою 0x00000) і являє собою ряд адрес із зміщенням сегментів, які вказують на ISR. ОС може замінити попередні записи IVT власними ISR.

(Примітка: Розмір IVT встановлений на рівні 1024 (0x400) байт.)

У захищеному (32-розрядному) режимі центральний процесор використовує IDT. IDT - це структура змінної довжини, яка складається з дескрипторів (інакше їх називають воротами), які повідомляють ЦП про обробники переривань. Структура цих дескрипторів набагато складніша, ніж прості записи про зміщення сегментів 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. ОС не обов’язково використовує всі з них, тому Present біт дозволяє процесору правильно обробляти переривання, які ОС не збирається обробляти.

Коли відбувається переривання (або зовнішнім тригером (наприклад, апаратним пристроєм) у IRQ, або intінструкцією програми), процесор штовхає EFLAGS, потім CS, а потім EIP. (Вони автоматично відновлюються iretінструкцією повернення переривання.) ОС зазвичай зберігає більше інформації про стан машини, обробляє переривання, відновлює стан машини і продовжує далі.

У багатьох операційних системах * NIX (включаючи Linux) системні дзвінки базуються на перериваннях. Програма поміщає аргументи до системного виклику в регістри (EAX, EBX, ECX, EDX тощо) і викликає переривання 0x80. Ядро вже встановило IDT, щоб містив обробник переривань на 0x80, який викликається, коли він отримує переривання 0x80. Потім ядро ​​читає аргументи і відповідно викликає функцію ядра. Він може зберігати повернення в EAX / EBX. Системні виклики були в значній мірі замінити sysenterі sysexit(або syscallі sysretна AMD) інструкції, які дозволяють швидше входу в кільце 0.

Це переривання може мати різне значення в іншій ОС. Обов’язково перевірте його документацію.


Цікавий факт: системний виклик i386 FreeBSD ABI передає аргументи в стек простору користувача. Використовується лише eaxдля номера syscall. asm.sourceforge.net/intro/hello.html
Пітер Кордес

2

Як уже згадувалося, це змушує управління переходити до вектора переривання 0x80. На практиці це означає (принаймні під Linux) те, що викликається системний виклик; точний системний виклик та аргументи визначаються вмістом регістрів. Наприклад, вихід () можна викликати, встановивши для% eax значення 1, а потім "int 0x80".


1

Він повідомляє процесору активувати вектор переривання 0x80, який в ОС Linux є перериванням системного виклику, що використовується для виклику системних функцій, таких як open()файли тощо.


9
Власне кажучи, це не повідомляє ядру ... Це повідомляє центральному процесору, який шукає обробник в IDT, який в кінцевому підсумку є вказівником на якийсь код ядра.
асвейкау

Правда. Я вважаю, що кращою фразою було б це, щоб він сказав процесору активувати вектор, а вектор (як частина ядра) викликає функцію.
Ембер

який в кінцевому підсумку робить це, який inturn закінчує робити те, що потім робить це, що потім йде туди розгубленим . : / У Ембер є відповідь, яка зрозуміла .. це все ..
Афзаал Ахмад Зеешан,

1

int - це не що інше, як переривання, тобто процесор утримує поточне виконання.

0x80 - це не що інше, як системний виклик або виклик ядра. тобто буде виконана функція системи.

Якщо бути конкретним, 0x80 представляє rt_sigtimedwait / init_module / restart_sys, він змінюється від архітектури до архітектури.

Детальніше див. Https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.