Pregunta

¿Alguien puede explicar qué hace el siguiente código de ensamblaje?

 int 0x80  
¿Fue útil?

Solución

Pasa el control para interrumpir el vector 0x80

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

En Linux, eche un vistazo a esto : se usó para manejar system_call . Por supuesto, en otro sistema operativo esto podría significar algo totalmente diferente.

Otros consejos

int significa interrupción, y el número 0x80 es el número de interrupción. Una interrupción transfiere el flujo del programa a quien esté manejando esa interrupción, que en este caso es interrupción 0x80 . En Linux, el controlador de interrupción 0x80 es el núcleo, y otros programas lo utilizan para hacer llamadas al sistema al núcleo.

El núcleo recibe una notificación sobre qué llamada al sistema desea realizar el programa, examinando el valor en el registro % eax (sintaxis de gas y EAX en la sintaxis de Intel). Cada llamada al sistema tiene requisitos diferentes sobre el uso de los otros registros. Por ejemplo, un valor de 1 en % eax significa una llamada al sistema de exit () , y el valor en % ebx contiene el valor del código de estado para exit () .

Tenga en cuenta que 0x80 = 80h = 128

Puede ver aquí que INT está solo una de las muchas instrucciones (en realidad, la representación en lenguaje ensamblador (o debería decir 'mnemónica')) que existe en el conjunto de instrucciones x86. También puede encontrar más información sobre esta instrucción en el propio manual de Intel que se encuentra aquí .

Para resumir del PDF:

  

INT n / INTO / INT 3: Llamada al procedimiento de interrupción

     

La instrucción INT n genera una llamada a la interrupción o excepción   controlador especificado con el operando de destino. El destino   El operando especifica un vector de 0 a 255, codificado como un signo de 8 bits sin signo   valor intermedio. La instrucción INT n es la mnemónica general para   ejecutar una llamada generada por software a un controlador de interrupciones.

Como puede ver, 0x80 es el operando de destino en su pregunta. En este punto, la CPU sabe que debe ejecutar algún código que reside en el Kernel, pero ¿qué código? Eso está determinado por el Vector de interrupción en Linux.

Una de las interrupciones de software de DOS más útiles fue la interrupción 0x21. Al llamarlo con diferentes parámetros en los registros (principalmente ah y al), puede acceder a varias operaciones de E / S, salida de cadena y más.

La mayoría de los sistemas y derivados de Unix no usan interrupciones de software, con la excepción de la interrupción 0x80, que se usa para hacer llamadas al sistema. Esto se logra ingresando un valor de 32 bits correspondiente a una función del núcleo en el registro EAX del procesador y luego ejecutando INT 0x80.

Observe esto, por favor, donde se muestran otros valores disponibles en las tablas del controlador de interrupciones:

ingrese la descripción de la imagen aquí

Como puede ver, la tabla señala que la CPU ejecuta una llamada al sistema. Puede encontrar la tabla de llamadas del sistema Linux aquí .

Entonces, moviendo el valor 0x1 al registro EAX y llamando al INT 0x80 en su programa, puede hacer que el proceso ejecute el código en Kernel que detendrá (saldrá) el proceso actual en ejecución (en Linux, CPU Intel x86) .

Una interrupción de hardware no debe confundirse con una interrupción de software. Aquí es muy Buena respuesta al respecto.

Esto también es una buena fuente.

Puede ver int 80h en acción aquí .

  

int 0x80 es el lenguaje ensamblador   instrucción que se usa para invocar   sistema de llamadas en Linux en x86 (es decir,   Procesadores compatibles con Intel).

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

Ejemplo de llamada de sistema Linux ejecutable mínimo

Linux configura el manejador de interrupciones para 0x80 de modo que implemente las llamadas del sistema, una forma para que los programas de usuario se comuniquen con el núcleo.

.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 
as -o main.o main.S
ld -o main.out main.o
./main.out
x80 movl $1, %eax /* exit system call number */ movl
hello world
, %ebx /* exit status */ int
    movw $handler0, 0x00
    mov %cs, 0x02
    movw $handler1, 0x04
    mov %cs, 0x06
    int <*>
    int $1
    hlt
handler0:
    /* Do 0. */
    iret
handler1:
    /* Do 1. */
    iret
x80

Compila y ejecuta con:

<*>

Resultado: el programa se imprime en stdout:

<*>

y sale limpiamente.

No puede configurar sus propios manejadores de interrupciones directamente desde userland porque solo tiene ring 3 y Linux te impide hacerlo .

syscall .

Consulte también: ¿Qué es mejor? & int; int 0x80 " o "syscall" "

Ejemplo mínimo de 16 bits

Primero, aprenda cómo crear un SO de gestor de arranque mínimo y ejecutarlo en QEMU y hardware real como lo he explicado aquí: https: / /stackoverflow.com/a/32483545/895245

Ahora puede ejecutar en modo real de 16 bits:

<*>

Esto haría en orden:

  • Do 0.
  • Do 1.
  • hlt : deja de ejecutar

Observe cómo el procesador busca el primer controlador en la dirección 0 , y el segundo en 4 : esa es una tabla de controladores llamada IVT , y cada entrada tiene 4 bytes.

Ejemplo mínimo que hace algún IO para hacer visibles los manejadores.

Ejemplo de modo protegido mínimo

Los sistemas operativos modernos se ejecutan en el llamado modo protegido.

El manejo tiene más opciones en este modo, por lo que es más complejo, pero el espíritu es el mismo.

El paso clave es utilizar las instrucciones LGDT y LIDT, que apuntan la dirección de una estructura de datos en memoria (la Tabla de descriptores de interrupción) que describe los controladores.

Ejemplo mínimo

El " int " la instrucción provoca una interrupción.

¿Qué es una interrupción?

Respuesta simple: Una interrupción, en pocas palabras, es un evento que interrumpe la CPU y le dice que ejecute una tarea específica.

Respuesta detallada :

La CPU tiene una tabla de Rutinas de servicio de interrupción (o ISR) almacenadas en la memoria. En el modo Real (16 bits), esto se almacena como IVT o I nterrupt V ector T poder. El IVT generalmente se encuentra en 0x0000: 0x0000 (dirección física 0x00000 ), y es una serie de direcciones de desplazamiento de segmento que apuntan a los ISR. El sistema operativo puede reemplazar las entradas IVT preexistentes con sus propios ISR.

(Nota: el tamaño del IVT se fija en 1024 (0x400) bytes).

En modo protegido (32 bits), la CPU utiliza un IDT. El IDT es una estructura de longitud variable que consta de descriptores (también conocidos como compuertas), que le informan a la CPU sobre los manejadores de interrupciones. La estructura de estos descriptores es mucho más compleja que las entradas simples de desplazamiento de segmento del IVT; aquí está:

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

* El IDT puede ser de tamaño variable, pero debe ser secuencial, es decir, si declara que su IDT es de 0x00 a 0x50, debe tener cada interrupción de 0x00 a 0x50. El sistema operativo no los usa necesariamente a todos, por lo que el bit Presente permite que la CPU maneje adecuadamente las interrupciones que el sistema operativo no tiene la intención de manejar.

Cuando ocurre una interrupción (ya sea por un disparador externo (por ejemplo, un dispositivo de hardware) en un IRQ, o por la instrucción int de un programa), la CPU empuja EFLAGS, luego CS, y luego EIP (Estos se restauran automáticamente mediante iret , la instrucción de retorno de interrupción). El sistema operativo generalmente almacena más información sobre el estado de la máquina, maneja la interrupción, restaura el estado de la máquina y continúa.

En muchos sistemas operativos * NIX (incluido Linux), las llamadas al sistema se basan en interrupciones. El programa coloca los argumentos de la llamada del sistema en los registros (EAX, EBX, ECX, EDX, etc.) y llama a la interrupción 0x80. El núcleo ya ha configurado el IDT para que contenga un controlador de interrupciones en 0x80, que se llama cuando recibe la interrupción 0x80. El núcleo lee los argumentos e invoca una función del núcleo en consecuencia. Puede almacenar una devolución en EAX / EBX. Las llamadas al sistema han sido reemplazadas en gran medida por las instrucciones sysenter y sysexit (o syscall y sysret en AMD), que permitir una entrada más rápida en el anillo 0.

Esta interrupción podría tener un significado diferente en un sistema operativo diferente. Asegúrese de revisar su documentación.

Como se mencionó, hace que el control salte para interrumpir el vector 0x80. En la práctica, lo que esto significa (al menos en Linux) es que se invoca una llamada al sistema; La llamada y los argumentos exactos del sistema están definidos por el contenido de los registros. Por ejemplo, se puede invocar exit () estableciendo% eax en 1 seguido de 'int 0x80'.

Le dice a la CPU que active el vector de interrupción 0x80, que en los sistemas operativos Linux es la interrupción de llamada al sistema, que se utiliza para invocar funciones del sistema como open () para archivos, etc.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top