Why Single Stepping Instruction on X86?

int 3 is a special 1-byte interrupt. Invoking it will break into the debugger if one is present, otherwise the application will typically crash.

When the debugger sets the trap flag, this causes the processor to automatically execute an int 1 interrupt after every instruction. This allows the debugger to single-step by instructions, without having to insert an int 3 instruction. You do not have to invoke this interrupt explicitly.


You are confusing the INT and INT 3 instructions with the interrupt vectors through which those instructions would call if the instruction were invoked. There is no single-step instruction.

The INT 3 (or "breakpoint instruction") will call the debugger if it is present (or rather, the debugger will hook the INT 3 vector so that when an INT 3 happens, the debugger will be called).

If the debugger sets the TF (trace flag), then every instruction will cause the #1 interrupt to occur. This will cause whatever address is in that interrupt vector to be called. Hopefully, this will be the single-step routine of a debugger. Eventually, the debugger will clear the TF, causing single-step interrupts to cease.


Others have already explained the distinction between the interrupt vector 1 and int 3 instruction.

Now, if you wonder why there're multiple interrupt vectors involved in handling of debug interrupts, I think it's just because the original 8086/8088 circuitry was intended to be relatively simple and to execute relatively simple software. It had very few special interrupt vectors and the int vector 1 was only used for the single-step trap and distinguishing it from the breakpoint trap was trivial, by the interrupt vector number, that is, it was sufficient to just have distinct handlers for the vector 1 and 3. That design was carried over to the x86 CPUs that followed. The newer CPUs substantially and "quickly" extended the set of the special interrupt vectors up to about 20 to handle new exceptions and extended the debugging functionality adding several other useful interrupt vector 1 triggers on top of the original single-step trap (e.g. instruction fetch, memory/port I/O, task switch, etc). It was logical to house most of them under the same interrupt vector since they're related and not consume more vectors.

Tags:

Debugging

X86

Gdb