ARM-----数据处理、异常处理、模式切换
 
 

实列一:
1. 异常向量表
area reset, code, readonly
code32
entry-  area reset, code, readonly:定义一个名为reset的代码区域,只读。
-  code32:指示编译器生成32位ARM指令。
-  entry:标记程序的入口点。
2. 程序入口和算术运算
start
    mov r0, #1                 ; r0 = 1
    mov r1, #2                 ; r1 = 2
    add r2, r0, r1             ; r2 = r0 + r1 = 3
    sub r3, r2, r1             ; r3 = r2 - r1 = 1-  mov r0, #1:将立即数1加载到寄存器r0。
-  mov r1, #2:将立即数2加载到寄存器r1。
-  add r2, r0, r1:将r0和r1相加,结果存入r2(r2 = 1 + 2 = 3)。
-  sub r3, r2, r1:将r2减去r1,结果存入r3(r3 = 3 - 2 = 1)。
3. 位运算
    mov r0, #0xff              ; r0 = 0xff (255)
    mov r1, #0x55              ; r1 = 0x55 (85)
    and r2, r0, r1             ; r2 = r0 & r1 = 0x55 (85)-  mov r0, #0xff:将立即数0xff(十进制255)加载到r0。
-  mov r1, #0x55:将立即数0x55(十进制85)加载到r1。
-  and r2, r0, r1:对r0和r1进行按位与操作,结果存入r2(r2 = 0xff & 0x55 = 0x55)。
4. 更多位运算
    mov r3, #0xaa              ; r3 = 0xaa (170)
    orr r4, r1, r3             ; r4 = r1 | r3 = 0xff (255)
    eor r5, r1, r3             ; r5 = r1 ^ r3 = 0xff (255)
    bic r3, r0, #3             ; r3 = r0 & ~3 = 0xfc (252)-  mov r3, #0xaa:将立即数0xaa(十进制170)加载到r3。
-  orr r4, r1, r3:对r1和r3进行按位或操作,结果存入r4(r4 = 0x55 | 0xaa = 0xff)。
-  eor r5, r1, r3:对r1和r3进行按位异或操作,结果存入r5(r5 = 0x55 ^ 0xaa = 0xff)。
-  bic r3, r0, #3:对r0进行按位与非操作,清除低3位,结果存入r3(r3 = 0xff & ~0x3 = 0xfc)。
5. 条件执行
    ; 0x 1 ffff ffff
    ; 0x 2 0000 0003
    ; 0x 4 0000 0002
    mov r0, #0x1               ; r0 = 1
    mov r1, #0xffffffff        ; r1 = 0xffffffff (-1 in two's complement)
    mov r2, #0x2               ; r2 = 2
    mov r3, #0x3               ; r3 = 3
    adds r5, r1, r3            ; r5 = r1 + r3 = 0xffffffff + 3 = 0x2 (with carry)
    adcs r4, r0, r2            ; r4 = r0 + r2 + carry = 1 + 2 + 1 = 4-  adds r5, r1, r3:将r1和r3相加,结果存入r5,并更新条件标志位。由于r1是0xffffffff(-1),加上3后结果为2,进位标志(C)被设置。
-  adcs r4, r0, r2:将r0和r2相加,并加上进位标志(C),结果存入r4(r4 = 1 + 2 + 1 = 4)。
6. 条件移动
    mov r0, #1                 ; r0 = 1
    mov r1, #3                 ; r1 = 3
    cmp r0, r1                 ; 比较r0和r1,设置条件标志位
    movgt r2, r0               ; 如果r0 > r1,将r0的值存入r2,否则r2保持原值
    movle r2, r1               ; 如果r0 <= r1,将r1的值存入r2-  cmp r0, r1:比较r0和r1,设置条件标志位。
-  movgt r2, r0:如果r0 > r1,将r0的值存入r2。
-  movle r2, r1:如果r0 <= r1,将r1的值存入r2。
7. 循环
    mov r0, #0                 ; r0 = 0
    mov r1, #0                 ; r1 = 0
loop
    add r0, r0, #1             ; r0 = r0 + 1
    add r1, r0, r1             ; r1 = r0 + r1
    cmp r0, #100               ; 比较r0和100
    blt loop                   ; 如果r0 < 100,跳转到loop-  mov r0, #0:将r0初始化为0。
-  mov r1, #0:将r1初始化为0。
-  loop:循环标签。-  add r0, r0, #1:r0递增1。
-  add r1, r0, r1:将r0和r1相加,结果存入r1。
-  cmp r0, #100:比较r0和100。
-  blt loop:如果r0 < 100,跳转到loop继续循环。
 
-  
8. 无限循环
    nop                        ; 空操作
    b start                    ; 无限循环,返回start
    end-  nop:空操作。
-  b start:跳转到start,形成无限循环。
实列二:
以下这段代码的主要功能是:
-  定义异常向量表,处理复位和软件中断。 
-  从SVC模式切换到USER模式。 
-  调用C语言函数 main。
-  实现一个简单的加法函数 asm_add。
1. 异常向量表
preserve8
area reset, code, readonly
code32
entry
b start          ; 复位异常
nop              ; 未定义异常
b deal_swi       ; 软件中断(SWI)
nop              ; 预取中止
nop              ; 数据中止
nop              ; 保留
nop              ; IRQ
nop              ; FIQ-  preserve8:确保代码对齐到8字节边界。
-  area reset, code, readonly:定义一个名为reset的代码区域,只读。
-  code32:指示编译器生成32位ARM指令。
-  entry:标记程序的入口点。
-  异常向量表:定义了处理器在发生不同异常时的处理程序入口。 -  b start:复位异常时跳转到start。
-  b deal_swi:软件中断(SWI)时跳转到deal_swi。
-  其他异常(如未定义异常、预取中止等)未处理,直接跳过。 
 
-  
2. 软件中断处理
deal_swi
    stmfd sp!, {r4-r12, lr}    ; 保存现场
    sub r0, lr, #4             ; 获取SWI号
    ldr r1, [r0]               ; 从内存中加载SWI号
    bic r0, r1, #(0xff << 24)  ; 清除SWI号的高8位
    ldmfd sp!, {r4-r12, pc}^   ; 恢复现场并返回-  stmfd sp!, {r4-r12, lr}:将寄存器r4到r12和链接寄存器lr压入堆栈,保存现场。
-  sub r0, lr, #4:从链接寄存器lr中提取SWI号。
-  ldr r1, [r0]:从内存中加载SWI号。
-  bic r0, r1, #(0xff << 24):清除SWI号的高8位。
-  ldmfd sp!, {r4-r12, pc}^:从堆栈中恢复寄存器r4到r12和程序计数器pc,并切换模式。
3. 程序入口
start
    ldr sp, =0x40001000        ; 设置SVC模式的堆栈指针
    mrs r0, cpsr               ; 将CPSR寄存器的值加载到r0
    bic r0, r0, #0x1f          ; 清除模式位(低5位)
    orr r0, r0, #0x10          ; 设置模式位为USER模式(0b10000)
    msr cpsr_c, r0             ; 将r0的值写回CPSR,切换到USER模式
    ldr sp, =0x40000c00        ; 设置USER模式的堆栈指针
    mov r0, #1                 ; 设置r0为1
    mov r1, #2                 ; 设置r1为2
    mov r6, #0x1               ; 设置r6为1
    import main                ; 导入C语言函数main
    bl main                    ; 调用main函数
    swi #0x7                   ; 触发软件中断,编号为0x7
    nop                        ; 空操作
    b start                    ; 无限循环,返回start-  ldr sp, =0x40001000:设置SVC模式的堆栈指针。
-  mrs r0, cpsr:将当前程序状态寄存器(CPSR)的值加载到r0。
-  bic r0, r0, #0x1f:清除r0的低5位(模式位)。
-  orr r0, r0, #0x10:设置模式位为USER模式(0b10000)。
-  msr cpsr_c, r0:将r0的值写回CPSR,切换到USER模式。
-  ldr sp, =0x40000c00:设置USER模式的堆栈指针。
-  bl main:调用C语言函数main。
-  swi #0x7:触发软件中断,编号为0x7。
-  b start:无限循环,返回start。
4. 简单加法函数
export asm_add
asm_add
    stmfd sp!, {r4-r12, lr}    ; 保存现场
    add r6, r0, r1             ; 将r0和r1相加,结果存入r6
    mov r0, r6                 ; 将结果存入r0
    ldmfd sp!, {r4-r12, pc}    ; 恢复现场并返回-  export asm_add:导出asm_add函数,使其可以被其他模块调用。
-  stmfd sp!, {r4-r12, lr}:将寄存器r4到r12和链接寄存器lr压入堆栈,保存现场。
-  add r6, r0, r1:将r0和r1相加,结果存入r6。
-  mov r0, r6:将结果存入r0。
-  ldmfd sp!, {r4-r12, pc}:从堆栈中恢复寄存器r4到r12和程序计数器pc,返回。
