I am trying to understand interrupts in x86 assembly.
I tried to trigger a divide-by-zero error, which corresponds to code 0.
int $0
I was expecting this to have the same behavior as dividing by zero.
movl $0, %edx # dividend
movl $0, %eax # dividend
movl $0, %edi # divisor
divl %edi
In the former case, my program crashes with a "Segmentation fault" and exit code 139 on Linux. In the latter case, my program crashes with a "Floating point exception" and exit code 136 on Linux.
How can I use an interrupt to trigger the same error as calling the div instruction with a zero divisor?
The operating system sets up the functions (interrupt handler, exception handler) for each event. When a divide by zero occurs, it triggers an exception. The CPU responds by invoking the exception handler in the interrupt vector corresponding to a divide by zero.
Xv6 maps the 32 hardware inter- rupts to the range 32-63 and uses interrupt 64 as the system call interrupt.
An interrupt is actually a call to a subroutine, but initiated by the peripheral hardware itself and not by the "CALL" instruction. The interrupt is asynchronous and can occur at any time during the execution of the main program.
Aborts are used to report severe errors, such as hardware failures and invalid or inconsistent values in system tables. The interrupt signal sent by the control unit is an emergency signal used to switch control to the corresponding abort exception handler.
I was expecting this to have the same behavior as dividing by zero.
In principle this is correct.
I tried to trigger a divide-by-zero error, which corresponds to code 0.
int $0
In principle this is still correct.
In the former case, my program crashes with a "Segmentation fault" and exit code 139 on Linux. In the latter case, my program crashes with a "Floating point exception" and exit code 136 on Linux.
x86 CPUs have two operating modes: Real Mode and Protected Mode (64-bit CPUs have a third mode: Long Mode)
In Real Mode you can execute any instruction the CPU is supporting in Real Mode. However Real Mode normally only allows 16-bit code and addressing up to 1 MB of memory. 32-bit operating systems run in Protected Mode.
In Protected Mode two special bits in the cs
register indicate if the code currently running belongs to the operating system kernel or to an application.
In Protected Mode ...
lmsw
) can only be called by the operating systemcli
) can only be called by applications if the operating system sets some special bits in some register; otherwise only the operating system can call these instructionsIf an application tries to do something which is not allowed (e.g. executing some instruction like lmsw
or int $0
) the CPU will cause an "Segmentation fault" interrupt (because the two bits in cs
are indicating that the code does not belong to the operating system). The forbidden instruction will NOT be executed!
If you would call int $0
from a kernel driver (on 32-bit Linux; not on 64-bit Linux) this should have the same effect as a division by zero.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With