通过SWI异常中断指令,在用户模式下应用程序可以调用系统模式下的代码,在操作系统中表现为系统调用, 那这个过程又是如何实现的呢?带着疑问让我们来学习吧!
在SWI指令中包括一个24位的立即数(中断调用号),该立即数指示了用户要请求的特定的调用功能,所以在SWI的异常中断中要读取这个中断调用号,然后根据中断号,来调用相应的处理程序。这个过程可以分两个步骤:
1.SWI异常中断处理程序 由于是在底层操作所以这个异常中断处理程序得用汇编语言编写,描述如下:
area top_swi code readonly export swi_headler swi_headler stmfd sp!, {r0-r12, lr} ; 保存r0至r12,lr的寄存器值 ldr r0, [lr, #-4] ; 从存储器中取得SWI指令的所在地址 bic r0, r0, #FF000000 ; 读取24位中断调用号 mov r1, sp ;================================================ bl swi_service_func ; 调用功能服务函数,见下面 ; 中断调用号通过r0寄存器传入 ; 参数通过r1寄存器传入 ;================================================ ldmfd sp!, {r0-r12, pc}^ ;恢复调用前的r0至r12,离开中断处理程序 end
2.功能服务程序 编写利用从中断处理函数获得的中断调用号我们可以写出如下服务函数(为了简单我们用C语言) void swi_service_func(unsigned int number, unsigned int *reg) { unsigned int reg1, reg2, reg3, reg4; //获取SWI前传入的参数 reg1 = reg[0]; reg2 = reg[1]; reg3 = reg[2]; reg4 = reg[3]; switch (number) { case 0: // do something break; case 1: // do something break; . . . case n: // do something break; default: // do something } } // 更新结果存入r0-r3 reg[0] = updata_reg1; reg[1] = updata_reg2; reg[2] = updata_reg3; reg[3] = updata_reg4; }
这样一来只要中调用断号不同就可以实现不同的功能调用了,是不是很简单? |