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 ...
- ... some instructions (e.g.
lmsw
) can only be called by the operating system
- ... some instructions (e.g.
cli
) 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 instructions
- ... memory access to some memory regions can be limited to the operating system
- ... jumping into the operating system code from application code is only allowed to certain addresses ...
- ... this also applies to interrupts: The operating system can decide which interrupts can be called by applications and which cannot.
If 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.