在ARM程序集中设置irq_handler

Ami*_*mar 2 assembly arm interrupt-handling arm7

我是ARM新手,了解ARM中的中断处理.我已经了解了如何在ARM中设置IRQ处理程序,但不确定如何在ARM程序集中编写它.以下是我对设置IRQ处理程序的理解.

_IRQ_HANDER:

1)SUB lr, lr, #4(不知道它做了什么).

2)在IRQ模式下应该设置单独的堆栈.我知道在x86中我们设置了如下堆栈:

push ebp
mov esp,ebp
sub esp,8
Run Code Online (Sandbox Code Playgroud)

这将重新产生8个字节的堆栈空间.

但不确定我在ARM中如何做同样的事情?

3)存储非存储寄存器,我们可以这样做:

  STMFD !sp {r13,r14}
Run Code Online (Sandbox Code Playgroud)

4)复制CPSR到SPSR(我怎么做ARM组装?)

5)转到处理器IRQ模式(我在ARM组件中可以这样做).

6)下一步是什么?

我们需要提供PIC的基址吗?

我正在使用ARMV7架构.

Sim*_*ter 6

  1. ARM上的程序计数器指向正在获取的指令,而不是当前指令.

    对于正常的子程序调用,这是完美的 - 当程序计数器被复制到链接寄存器时,它已经指向下一条指令.在中断处理程序中,它指向中断指令之后的指令,因此需要对其进行纠正.

    您也可以在出路时应用此更正,例如通过返回SUBS pc, lr, #4.请注意,如果中断的代码在Thumb模式下运行,lr则前面只有两个字节,因此如果要在Thumb模式下支持用户代码,则需要查看spsr_IRQ要找出要应用的偏移量.

  2. 在ARM上,由于寄存器存储,您已经有一个单独的堆栈.当进入智商模式,寄存器r13又名sp并r14又名lr被切换至r13_IRQ和r14_IRQ,这就是为什么你不需要恢复lr退出你的中断处理程序时被中断的应用程序.

    需要在第一次中断发生之前设置此堆栈.内核启动代码在某些时候通过更改状态寄存器从初始SVC模式切换到IRQ模式,此时r13_IRQ寄存器变为可见,将初始堆栈指针写入那里并切换回SVC模式.

    通过从堆栈指针中减去,例如使用,扩展堆栈帧的工作方式基本上与x86相同SUB sp,sp,#8.

    您粘贴的x86代码不仅仅是扩展堆栈空间:它还构建了一个基本指针链,如果您希望调试器显示调用堆栈,这将非常有用.为了实现这一点,您需要根据ABI填写完整的堆栈帧,并在特定的插槽中保存返回地址等,我认为这是一个高级主题.如果您希望在从中断处理程序调用的C函数中使用调试器,则可以调用r12设置为零的第一个C函数,这将使基指针链终止于您的处理函数而不是混淆调试器.

  3. 你有它倒退 - 这两个寄存器是存储的,不需要保存,除非你在处理程序中重新启用中断.您需要保存处理程序使用的任何寄存器,并在返回之前恢复它们,STore Multiple Full Descending(STMFD)指令对此是正确的.

  4. 这也是倒退.您想保存spsr_IRQ寄存器而不是覆盖它.同样,这是一个存储区寄存器,因此如果在处理程序返回之前需要更多中断(即清除PSR中的"中断禁用"位),则只需执行此操作.

  5. 你已经在IRQ模式中了.你离开IRQ模式通过设置状态寄存器的一个新的模式,或使用指令时用的S后缀(MOVS,SUBS,ADDS,...)来设定pc从lr(以下简称"设置状态寄存器"在此背景下位意味着"副本SPSR到PSR").

  6. 之后,您可以处理IRQ的原因,通常是询问中断控制器(它位于ARM内核之外,因此它取决于模型)发生了什么,然后分支到相应的代码路径中.根据时序约束,您可以处理整个事件,或者只是快速记录中断发生的空闲循环,并在下次系统空闲时调用相应的函数.

从IRQ返回,你需要清理IRQ栈,恢复任何非编组的寄存器,然后用MOVS,SUBS或类似的指令集pc和cpsr在同一时间.