Что означает “int 0x80” в ассемблерном коде?

StackOverflow https://stackoverflow.com/questions/1817577

  •  08-07-2019
  •  | 
  •  

Вопрос

Кто-нибудь может объяснить, что делает следующий ассемблерный код?

 int 0x80  
Это было полезно?

Решение

Он передает управление на вектор прерывания 0x80

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

В Linux посмотрите это : оно использовалось для обработки system_call . Конечно, на другой ОС это может означать что-то совершенно другое.

Другие советы

int означает прерывание, а число 0x80 является номером прерывания. Прерывание передает поток программы тому, кто обрабатывает это прерывание, в данном случае это прерывание 0x80 . В Linux обработчик прерываний 0x80 является ядром и используется для выполнения системных вызовов ядра другими программами.

Ядро уведомляется о том, какой системный вызов хочет сделать программа, проверяя значение в регистре % eax (синтаксис gas и EAX в синтаксисе Intel). Каждый системный вызов предъявляет разные требования к использованию других регистров. Например, значение 1 в % eax означает системный вызов exit () , а значение в % ebx содержит значение кода состояния для exit () .

Имейте в виду, что 0x80 = 80h = 128

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

Подводя итог из PDF:

  

INT n / INTO / INT 3 & # 8212; Вызов процедуры прерывания

     

Инструкция INT n генерирует вызов прерывания или исключения   обработчик, указанный с операндом назначения. Пункт назначения   операнд задает вектор от 0 до 255, закодированный как 8-битный без знака   промежуточное значение. Инструкция INT n является общей мнемоникой для   выполнение программно-сгенерированного вызова обработчика прерываний.

Как вы можете видеть 0x80 - это целевой операнд в вашем вопросе. В этот момент процессор знает, что он должен выполнить некоторый код, который находится в ядре, но какой код? Это определяется вектором прерывания в Linux.

Одним из наиболее полезных программных прерываний для DOS было прерывание 0x21. Вызывая его с различными параметрами в регистрах (в основном, ah и al), вы можете получить доступ к различным операциям ввода-вывода, выводу строки и многому другому.

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

Посмотрите на это, где показаны другие доступные значения в таблицах обработчиков прерываний:

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

Как видно из таблицы, процессор указывает на выполнение системного вызова. Вы можете найти таблицу системных вызовов Linux здесь .

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

Аппаратное прерывание не следует путать с программным прерыванием. Здесь очень хороший ответ на этот счет.

Этот также является хорошим источником.

Вы можете увидеть int 80h в действии .

  

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

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

Пример минимального выполняемого системного вызова 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" или "системный вызов"?

Минимальный 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 байта.

Минимальный пример, который выполняет некоторый ввод-вывод чтобы сделать обработчики видимыми.

Пример минимального защищенного режима

Современные операционные системы работают в так называемом защищенном режиме.

В этом режиме управление имеет больше возможностей, поэтому оно более сложное, но дух тот же.

Ключевым шагом является использование инструкций LGDT и LIDT, которые указывают адрес структуры данных в памяти (таблицы дескрипторов прерываний), описывающей обработчики.

Минимальный пример

Команда "int" вызывает прерывание.

Что такое прерывание?

Простой Ответ: Проще говоря, прерывание - это событие, которое прерывает работу центрального процессора и сообщает ему выполнить определенную задачу.

Подробный Ответ:

Центральный процессор имеет таблицу процедур обслуживания прерываний (или ISR), хранящихся в памяти.В реальном (16-разрядном) режиме это сохраняется как IVT, или Янарушенный Vэктор Tспособный.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.ОС не обязательно использует их все, поэтому данный бит позволяет центральному процессору должным образом обрабатывать прерывания, которые ОС обрабатывать не намерена.

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

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

Это прерывание может иметь другое значение в другой операционной системе.Обязательно ознакомьтесь с его документацией.

Как уже упоминалось, он заставляет элемент управления перейти к вектору прерывания 0x80. На практике это означает (по крайней мере, в Linux), что системный вызов вызывается; точный системный вызов и аргументы определяются содержимым регистров. Например, exit () можно вызвать, установив% eax в 1, за которым следует 'int 0x80'.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top