Home » 插件 » Arm 异常处理 - 中断异常

Arm 异常处理 - 中断异常

编 辑:Y ┊ 时 间:2022年03月03日 ┊ 访问: 21 次

78843-wqr1ty4utpd.png

01070-laa0uska3z9.png

87540-75mnis91qn.png

89137-chte0u4ommp.png

64633-bjzbccu3h2.png

13336-9aujkjh9824.png

75368-w4bh5d3aep.png

.text
    @mov r0, #1
    @Òì³£ÏòÁ¿±í
    b    reset    @0x00 reset
    nop         @0x04 udef
    nop            @0x08
    nop         @0x10
    nop            @0x14
    nop            @0x18 irq
    nop            @0x1c fiq
    

reset:
    mov r0,#3
    swi 2
    b reset

.end

现在我们加上现场保护的机制

.text
    @mov r0, #1
    @Òì³£ÏòÁ¿±í
    b    reset    @0x00 reset
    nop         @0x04 udef
    b    swi_handler        @0x08
    nop            @0x0c
    nop         @0x10
    nop            @0x14
    nop            @0x18 irq
    nop            @0x1c fiq

swi_handler:        @ÈíÖжϴ¦Àíº¯Êý
    stmfd sp!, {r0, lr}        @½øÕ» ±£»¤ÏÖ³¡
    mov        r0, #6
    ldmfd sp!, {r0, pc}        @ ³öÕ»»Ö¸´ÏÖ³¡
    mov pc, lr      @lr¸³Öµµ½pc
    

reset:
    ldr sp,=stack_base
    mov r0,#3
    swi 2    @Ìø×ªµ½Òì³£ÏòÁ¿±íÖÐÈíÖжϵÄÈë¿ÚλÖÃ
             @±£´æ·µ»ØµØÖ·µ½lr
    mov r1, r0
    b reset


    .data
buf:
    .space 32
stack_base:
    

.end

55604-p6gd3w2jwc9.png

软中断是可以切换至super模式的
56909-q6ce0aeliu.png

我们根据上面代码先将它切换到用户模式,随后软中断将他切换到super的模式

但是我们发现它中断处理结束后,没有切回到user模式
51902-mtsatf697ng.png

user模式和svc模式R13(SP)不是同一个



.text
    @mov r0, #1
    @Òì³£ÏòÁ¿±í
    b    reset    @0x00 reset
    nop         @0x04 udef
    b    swi_handler        @0x08
    nop            @0x0c
    nop         @0x10
    nop            @0x14
    nop            @0x18 irq
    nop            @0x1c fiq

swi_handler:        @ÈíÖжϴ¦Àíº¯Êý
    stmfd sp!, {r0, lr}        @½øÕ» ±£»¤ÏÖ³¡
    mov        r0, #6
    ldmfd sp!, {r0, pc}^        @ ³öÕ»»Ö¸´ÏÖ³¡
    mov pc, lr      @lr¸³Öµµ½pc
    

reset:
    ldr sp,=stack_base
    @Çл»µ½Ó¦ÓõÄģʽ£¨user£©
    msr cpsr , #0x10
    mov r0,#3
    swi 2    @Ìø×ªµ½Òì³£ÏòÁ¿±íÖÐÈíÖжϵÄÈë¿ÚλÖÃ
             @±£´æ·µ»ØµØÖ·µ½lr
    mov r1, r0
    b reset


    .data
buf:
    .space 32
stack_base:
    

.end

我们将ldr sp,=stack_base放到了上面,但是还是有问题,切换不回去
99764-0ti7huqfe6ih.png
01402-0qefl1uzsu7.png

通过一个向上的小箭头,就会恢复到之前的工作模式

70231-zutuvdbv0gn.png

43591-1a6xapfa2in.png

48067-5ftmzh2kdwg.png

成功

其他软中断

34227-6md8qa92v1d.png

找到软中断地址获得最低的24位

@取软中断地址 软中断下一位-4就是软中断的位置
    sub r0, lr, #4
    @取地址内容  通过地址获取内容
    ldr r0, [r0]
    @只保留最低的24位
    @所以执行一下清除操作
    bic r0, #0xff000000
    @这样就获得了软中断号

完整代码:



.text
    @mov r0, #1
    @异常向量表
    b    reset    @0x00 reset
    nop         @0x04 udef
    b    swi_handler        @0x08
    nop            @0x0c
    nop         @0x10
    nop            @0x14
    nop            @0x18 irq
    nop            @0x1c fiq

swi_handler:        @软中断处理函数
    stmfd sp!, {r0, lr}        @进栈 保护现场
    
    
    @取软中断地址 软中断下一位-4就是软中断的位置
    sub r0, lr, #4
    @取地址内容  通过地址获取内容
    ldr r0, [r0]
    @只保留最低的24位
    @所以执行一下清除操作
    bic r0, #0xff000000
    @这样就获得了软中断号
    
    @mov        r0, #6
    bl        swi_num_handler
    ldmfd sp!,{r0, pc}^        @ 出栈恢复现场
    @ mov pc, lr      @lr赋值到pc
    
swi_num_handler:
    @swicth(num):
    @case...
    @....
    
    mov pc, lr


reset:
    ldr sp,=stack_base
    @切换到应用的模式(user)
    msr cpsr , #0x10
    mov r0,#3
    swi 2    @跳转到异常向量表中软中断的入口位置
             @保存返回地址到lr
             @切换刀SVC模式
    mov r1, r0
    
    swi        4
    mov        r6, #3
    nop
    nop
    swi        7
    mov        r8, #0
    
    
    b reset


    .data
buf:
    .space 32
stack_base:
.end

63270-mk790zc4kcp.png

判断:
66875-vhxzikcpe78.png



.text
    @mov r0, #1
    @异常向量表
    b    reset    @0x00 reset
    nop         @0x04 udef
    b    swi_handler        @0x08
    nop            @0x0c
    nop         @0x10
    nop            @0x14
    nop            @0x18 irq
    nop            @0x1c fiq

swi_handler:        @软中断处理函数
    stmfd sp!, {r0, lr}        @进栈 保护现场
    
    
    @取软中断地址 软中断下一位-4就是软中断的位置
    sub r0, lr, #4
    @取地址内容  通过地址获取内容
    ldr r0, [r0]
    @只保留最低的24位
    @所以执行一下清除操作
    bic r0, #0xff000000
    @这样就获得了软中断号
    
    bl        swi_num_handler
    ldmfd sp!,{r0, pc}^        @ 出栈恢复现场
    @ mov pc, lr      @lr赋值到pc
    
swi_num_handler:
    @swicth(num):
    @case...
    @....
    cmp r0, #2
    moveq r7, #2
    cmp r0, #4
    moveq r7, #4
    cmp r0, #8
    moveq r7, #8
    
    mov pc, lr


reset:
    ldr sp,=stack_base
    @切换到应用的模式(user)
    msr cpsr , #0x10
    mov r0,#3
    swi 2    @跳转到异常向量表中软中断的入口位置
             @保存返回地址到lr
             @切换刀SVC模式
    mov r1, r0
    
    swi        4
    mov        r6, #3
    nop
    nop
    swi        7
    mov        r8, #0
    
    
    b reset


    .data
buf:
    .space 32
stack_base:
    

.end

85806-9jjuk1gd5li.png

突破32M空间限制(swi_handler如果地址很大)

11915-v805wxp603.png

mov 只能放32位的,太大的情况会出问题
有可能b指令放不下
所以可以使用ldr指令:

ldr pc, _swi_handler

_swi_handler:
   .word swi_handler

05253-ngchc8ctw3s.png

类似下图
53827-gpv5y4qzceh.png

.text
    @mov r0, #1
    @异常向量表
    b    reset    @0x00 reset
    nop         @0x04 udef
    @b    swi_handler         @0x08
    ldr    pc, _swi_handler @0x08
    @把ldr获取的内容赋值给pc
    @为了突破32M空间的限制
    
    nop            @0x0c
    nop         @0x10
    nop            @0x14
    nop            @0x18 irq
    nop            @0x1c fiq

_swi_handler:  @标号就是个地址  swi_handler数比较特殊,是个函数地址
    .word     swi_handler   @.word占四个字节数
    @ ...
    @ ...
    @ ...
 
swi_handler:        @软中断处理函数
    stmfd sp!, {r0, lr}        @进栈 保护现场
    
    
    @取软中断地址 软中断下一位-4就是软中断的位置
    sub r0, lr, #4
    @取地址内容  通过地址获取内容
    ldr r0, [r0]
    @只保留最低的24位
    @所以执行一下清除操作
    bic r0, #0xff000000
    @这样就获得了软中断号
    
    bl        swi_num_handler
    ldmfd sp!,{r0, pc}^        @ 出栈恢复现场
    @ mov pc, lr      @lr赋值到pc
    
swi_num_handler:
    @swicth(num):
    @case...
    @....
    cmp r0, #2
    moveq r7, #2
    cmp r0, #4
    moveq r7, #4
    cmp r0, #8
    moveq r7, #8
    
    mov pc, lr

如果以前用b指令跳转,函数可能地址很大,就会出错
b指令存储地址的空间是有限的
所以我们只能把这个地址单纯用一个四个字节空间来存放
通过间接的方式去获取
ldr获取的时候是通过相对偏移来获取
所以现在地址多大都无所谓,不会超过32位
通过两种方式,就突破了32M



.text
    @mov r0, #1
    @异常向量表
    b    reset    @0x00 reset
    nop         @0x04 udef
    @b    swi_handler         @0x08
    ldr    pc, _swi_handler @0x08
    @把ldr获取的内容赋值给pc
    @为了突破32M空间的限制
    
    nop            @0x0c
    nop         @0x10
    nop            @0x14
    nop            @0x18 irq
    nop            @0x1c fiq

_swi_handler:  @标号就是个地址  swi_handler数比较特殊,是个函数地址
    .word     swi_handler   @.word占四个字节数
    @ ...
    @ ...
    @ ...
 
swi_handler:        @软中断处理函数
    stmfd sp!, {r0, lr}        @进栈 保护现场
    
    
    @取软中断地址 软中断下一位-4就是软中断的位置
    sub r0, lr, #4
    @取地址内容  通过地址获取内容
    ldr r0, [r0]
    @只保留最低的24位
    @所以执行一下清除操作
    bic r0, #0xff000000
    @这样就获得了软中断号
    
    bl        swi_num_handler
    ldmfd sp!,{r0, pc}^        @ 出栈恢复现场
    @ mov pc, lr      @lr赋值到pc
    
swi_num_handler:
    @swicth(num):
    @case...
    @....
    cmp r0, #2
    moveq r7, #2
    cmp r0, #4
    moveq r7, #4
    cmp r0, #8
    moveq r7, #8
    
    mov pc, lr


reset:
    ldr sp,=stack_base
    @切换到应用的模式(user)
    msr cpsr , #0x10
    mov r0,#3
    swi 2    @跳转到异常向量表中软中断的入口位置
             @保存返回地址到lr
             @切换刀SVC模式
    mov r1, r0
    
    swi        4
    mov        r6, #3
    nop
    nop
    swi        7
    mov        r8, #0
    
    
    b reset


    .data
buf:
    .space 32
stack_base:
.end

尝试完善中断

66785-sg1ttdpd1q.png



.text
    @mov r0, #1
    @异常向量表
    b    reset    @0x00 reset
    ldr pc,_udef                 @0x04 udef
    @b    swi_handler                 @0x08
    ldr    pc, _swi_handler         @0x08
    @把ldr获取的内容赋值给pc
    @为了突破32M空间的限制
    
    ldr pc, _prefech            @0x0c
    ldr pc, _data_abort         @0x10
    nop                            @0x14
    ldr pc, _irq                @0x18 irq
    ldr pc, _fiq                @0x1c fiq
    
_udef:
    .word _udef

_prefech:
    .word _prefech

_data_abort:
    .word _data_abort
    
_irq:
    .word _irq
    
_fiq:
    .word _fiq


_swi_handler:  @标号就是个地址  swi_handler数比较特殊,是个函数地址
    .word     swi_handler   @.word占四个字节数
    @ ...
    @ ...
    @ ...
 
swi_handler:        @软中断处理函数
    stmfd sp!, {r0, lr}        @进栈 保护现场
    
    
    @取软中断地址 软中断下一位-4就是软中断的位置
    sub r0, lr, #4
    @取地址内容  通过地址获取内容
    ldr r0, [r0]
    @只保留最低的24位
    @所以执行一下清除操作
    bic r0, #0xff000000
    @这样就获得了软中断号
    
    bl        swi_num_handler
    ldmfd sp!,{r0, pc}^        @ 出栈恢复现场
    @ mov pc, lr      @lr赋值到pc
    
swi_num_handler:
    @swicth(num):
    @case...
    @....
    cmp r0, #2
    moveq r7, #2
    cmp r0, #4
    moveq r7, #4
    cmp r0, #8
    moveq r7, #8
    
    mov pc, lr


reset:
    ldr sp,=stack_base
    @切换到应用的模式(user)
    msr cpsr , #0x10
    mov r0,#3
    swi 2    @跳转到异常向量表中软中断的入口位置
             @保存返回地址到lr
             @切换刀SVC模式
    mov r1, r0
    
    swi        4
    mov        r6, #3
    nop
    nop
    swi        7
    mov        r8, #0
    
    
    b reset


    .data
buf:
    .space 32
stack_base:
.end

本次难点:
28829-opcp5m0teq.png

现在看复杂的程序和uboot就没问题了




Copyright © 2026 Y 版权所有.网站运行:13年238天21小时25分