Saving and restoring registers
Since an interrupt causes control to transfer to another function, we need to save the registers, so as to preserve their content. For example, let’s suppose that while executing a particular function F
, an interrupt occurs:
void F() { ........ ........ ........ (Interrupt Occurs) ........ ........ ........ }
Let’s suppose we have a function INTR
that is invoked when the interrupt occurs:
static void INTR() { ........ ........ ........ }
It is possible that the value of some of the registers being used by F()
are also used by INTR()
. So, if we don’t preserve their content, they will be corrupted by INTR()
. So, we take a backup of the registers inside the interrupt function (while entering the interrupt function), and restore them while exiting the function, as follows:
static void INTR() { // Take backup of registers used ........ ........ ........ // Restore the registers }
Now, let us look at an example to see how the registers will be saved in memory. To understand this example, let’s assume that we have a processor that supports:
- Data registers — R0, R1, R2
- Address registers — AR0
- Instructions in which the first operand forms the destination operand. And the remaining operands form the source operands.
Please note that we need to save those registers that are used by the interrupt function. Let’s look at the following example for the interrupt routine INTR()
:
static void INTR() { int a, b, c ; a = b + c; }
The saving and restoring of registers is done as shown below:
_intr: // Prologue Code ... ... // Taking Backup of Data Registers // used in the interrupt routine MOVE [AR0]++,R0; MOVE [AR0]++,R1; MOVE [AR0]++,R2; // a = b + c; MOVE AR0, SP ; //SP is the stack pointer MOVE R2, [AR0]++ ; MOVE R1, [AR0]++ ; ADD R0, R2, R1 ; MOVE [AR0]++, R0 ; //Restore ARO by the stack pointer // Restoring Data Registers // used in the interrupt routine MOVE R2, [AR0]--; MOVE R1, [AR0]--; MOVE R0, [AR0] ; // Epilogue Code ... ... RETINT ; //Return from interrupt routine END
As you can see above, since we know what registers are used in the interrupt routine, we need to preserve only (the values of) those registers. A better (but suboptimal) way would be to blindly save/restore all the physical registers, so that in future, if the interrupt routine is modified, you need not bother about additional code for saving/restoring the new set of registers used in the function. However, this may be subject to requirements.