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


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

 int 0x80  
8 63

8 ответов:

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

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

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

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

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

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

вы можете ознакомиться здесь это INT - это всего лишь одна из многих инструкций (на самом деле представление языка ассемблера (или я должен сказать "мнемонический")), которая существует в наборе инструкций x86. Вы также можете найти дополнительную информацию об этой инструкции в Intel's own manual found здесь.

чтобы подвести итог из 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.

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

enter image description here

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

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

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

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

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

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

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

минимальный запускаемый пример системного вызова Linux

Linux устанавливает обработчик прерываний для 0x80 таким образом, что он реализует системные вызовы, способ для программ userland для связи с ядром.

.data
    s:
        .ascii "hello world\n"
        len = . - s
.text
    .global _start
    _start:

        movl , %eax   /* write system call number */
        movl , %ebx   /* stdout */
        movl $s, %ecx   /* the data to print */
        movl $len, %edx /* length of the buffer */
        int x80

        movl , %eax   /* exit system call number */
        movl , %ebx   /* exit status */
        int x80

скомпилировать и запустить с:

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 был заменен лучшими альтернативами для выполнения системных вызовов: first sysenter, затем ВДСО.

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 
    int 
    hlt
handler0:
    /* Do 0. */
    iret
handler1:
    /* Do 1. */
    iret

это будет делать по порядку:

  • Do 0.
  • Do 1.
  • hlt: остановка выполнение

обратите внимание, как процессор ищет первый обработчик по адресу 0, а второй в 4: это таблица обработчиков называется IVT, и каждая запись имеет 4 байта.

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

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

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

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

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

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

инструкция "int" вызывает прерывание.

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

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

Подробный Ответ!--15-->:

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

во многих * 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() для файлов, и так далее.