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

news2025/4/6 19:37:43

 

实列一:

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:将r0r1相加,结果存入r2r2 = 1 + 2 = 3)。

  • sub r3, r2, r1:将r2减去r1,结果存入r3r3 = 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:对r0r1进行按位与操作,结果存入r2r2 = 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:对r1r3进行按位或操作,结果存入r4r4 = 0x55 | 0xaa = 0xff)。

  • eor r5, r1, r3:对r1r3进行按位异或操作,结果存入r5r5 = 0x55 ^ 0xaa = 0xff)。

  • bic r3, r0, #3:对r0进行按位与非操作,清除低3位,结果存入r3r3 = 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:将r1r3相加,结果存入r5,并更新条件标志位。由于r1是0xffffffff(-1),加上3后结果为2,进位标志(C)被设置。

  • adcs r4, r0, r2:将r0r2相加,并加上进位标志(C),结果存入r4r4 = 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:比较r0r1,设置条件标志位。

  • 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, #1r0递增1。

    • add r1, r0, r1:将r0r1相加,结果存入r1

    • cmp r0, #100:比较r0和100。

    • blt loop:如果r0 < 100,跳转到loop继续循环。

8. 无限循环

    nop                        ; 空操作
    b start                    ; 无限循环,返回start

    end
  • nop:空操作。

  • b start:跳转到start,形成无限循环。

实列二:

以下这段代码的主要功能是:

  1. 定义异常向量表,处理复位和软件中断。

  2. 从SVC模式切换到USER模式。

  3. 调用C语言函数main

  4. 实现一个简单的加法函数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}:将寄存器r4r12和链接寄存器lr压入堆栈,保存现场。

  • sub r0, lr, #4:从链接寄存器lr中提取SWI号。

  • ldr r1, [r0]:从内存中加载SWI号。

  • bic r0, r1, #(0xff << 24):清除SWI号的高8位。

  • ldmfd sp!, {r4-r12, pc}^:从堆栈中恢复寄存器r4r12和程序计数器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}:将寄存器r4r12和链接寄存器lr压入堆栈,保存现场。

  • add r6, r0, r1:将r0r1相加,结果存入r6

  • mov r0, r6:将结果存入r0

  • ldmfd sp!, {r4-r12, pc}:从堆栈中恢复寄存器r4r12和程序计数器pc,返回。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2328763.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

d202541

目录 一、分隔链表 二、旋转链表 三、删除链表中重复的数字 一、分隔链表 用两个list存一下小于和大于等于 x的节点 最后串起来就行 public ListNode partition(ListNode head, int x) {ListNode ret new ListNode(1);ListNode cur ret;List<ListNode> small new A…

YOLOv12 从预训练迈向自主训练,第一步数据准备

视频讲解&#xff1a; YOLOv12 从预训练迈向自主训练&#xff0c;第一步数据准备 前面复现过yolov12&#xff0c;使用pre-trained的模型进行过测试&#xff0c;今天来讲下如何训练自己的模型&#xff0c;第一步先准备数据和训练格式 https://gitcode.com/open-source-toolkit/…

【UVM学习笔记】更加灵活的UVM—通信

系列文章目录 【UVM学习笔记】UVM基础—一文告诉你UVM的组成部分 【UVM学习笔记】UVM中的“类” 文章目录 系列文章目录前言一、TLM是什么&#xff1f;二、put操作2.1、建立PORT和EXPORT的连接2.2 IMP组件 三、get操作四、transport端口五、nonblocking端口六、analysis端口七…

NSSCTF [HGAME 2023 week1]simple_shellcode

3488.[HGAME 2023 week1]simple_shellcode 手写read函数shellcode和orw [HGAME 2023 week1]simple_shellcode (1) motalymotaly-VMware-Virtual-Platform:~/桌面$ file vuln vuln: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpret…

数据集(Dataset)和数据加载器(DataLoader)-pytroch学习3

pytorch网站学习 处理数据样本的代码往往会变得很乱、难以维护&#xff1b;理想情况下&#xff0c;我们希望把数据部分的代码和模型训练部分分开写&#xff0c;这样更容易阅读、也更好维护。 简单说&#xff1a;数据和模型最好“分工明确”&#xff0c;不要写在一起。 PyTor…

数据结构|排序算法(一)快速排序

一、排序概念 排序是数据结构中的一个重要概念&#xff0c;它是指将一组数据元素按照特定的顺序进行排列的过程&#xff0c;默认是从小到大排序。 常见的八大排序算法&#xff1a; 插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序、归并排序、基数排序 二、快速…

文件或目录损坏且无法读取:数据恢复的实战指南

在数字化时代&#xff0c;数据的重要性不言而喻。然而&#xff0c;在日常使用电脑、移动硬盘、U盘等存储设备时&#xff0c;我们难免会遇到“文件或目录损坏且无法读取”的提示。这一提示如同晴天霹雳&#xff0c;让无数用户心急如焚&#xff0c;尤其是当这些文件中存储着重要的…

leetcode数组-螺旋矩阵Ⅱ

题目 题目链接&#xff1a;https://leetcode.cn/problems/spiral-matrix-ii/ 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7…

小刚说C语言刷题——第14讲 逻辑运算符

当我们需要将一个表达式取反&#xff0c;或者要判断两个表达式组成的大的表达式的结果时&#xff0c;要用到逻辑运算符。 1.逻辑运算符的分类 (1)逻辑非(!) &#xff01;a&#xff0c;当a为真时&#xff0c;&#xff01;a为假。当a为假时&#xff0c;&#xff01;a为真。 例…

WPS宏开发手册——Excel实战

目录 系列文章5、Excel实战使用for循环给10*10的表格填充行列之和使用for循环将10*10表格中的偶数值提取到另一个sheet页使用for循环给写一个99乘法表按市场成员名称分类&#xff08;即市场成员A、B、C...&#xff09;&#xff0c;统计月内不同时间段表1和表2的乘积之和&#x…

【Cursor】切换主题

右键顶部&#xff0c;把菜单栏勾上 首选项-主题-颜色主题 选择和喜欢的颜色主题即可&#xff0c;一般是“现代深色”

spring druid项目中监控sql执行情况

场景 在 Spring Boot 结合 MyBatis 的服务中&#xff0c;实现 SQL 执行覆盖情况的监控&#xff0c;可以基于Druid提供的内置的 SQL 监控统计功能。 开启监控 在 application.yml 中启用 Druid 的 stat 和 wall 过滤器&#xff0c;并配置监控页面的访问权限 …

Obsidian按下三个横线不能出现文档属性

解决方案: 需要在标题下方的一行, 按下 键盘数字0后面那个横线(英文横线), 然后回车就可以了 然后点击横线即可

pyqt SQL Server 数据库查询-优化2

1、增加导出数据功能 2、增加删除表里数据功能 import sys import pyodbc from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QListWidget, QLineEdit, QPushButton, \QTableWidget, QTableWidgetItem, QLabel, QMessageBox from PyQt6.QtGui i…

Hyperlane:高性能 Rust HTTP 服务器框架评测

Hyperlane&#xff1a;高性能 Rust HTTP 服务器框架评测 在当今快速发展的互联网时代&#xff0c;选择一个高效、可靠的 HTTP 服务器框架对于开发者来说至关重要。最近&#xff0c;我在评估各种服务器框架性能时&#xff0c;发现了一个名为 Hyperlane 的 Rust HTTP 服务器库&a…

Laravel 中使用 JWT 作用户登录,身份认证

什么是JWT&#xff1a; JWT 全名 JSON Web Token&#xff0c;是一种开放标准 (RFC 7519)。 用于在网络应用环境间安全地传输信息作为 JSON 对象。 它是一种轻量级的认证和授权机制&#xff0c;特别适合分布式系统的身份验证。 核心特点 紧凑格式&#xff1a;体积小&#x…

VBA中类的解读及应用第二十二讲:利用类判断任意单元格的类型-5

《VBA中类的解读及应用》教程【10165646】是我推出的第五套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。 类&#xff0c;是非常抽象的&#xff0c;更具研究的价值。随着我们学习、应用VBA的深入&#xff0…

STM32F103_LL库+寄存器学习笔记13 - 梳理外设CAN与如何发送CAN报文(串行发送)

导言 CAN总线因其高速稳定的数据传输与卓越抗干扰性能&#xff0c;在汽车、机器人及工业自动化中被广泛应用。它采用分布式网络结构&#xff0c;实现多节点间实时通信&#xff0c;确保各控制模块精准协同。在汽车领域&#xff0c;CAN总线连接发动机、制动、车身系统&#xff0c…

Linux系统调用编程

文章目录 一、进程和线程二、Linux的虚拟内存管理和stm32的真实物理内存**Linux虚拟内存管理**STM32物理内存映射2. 主要区别 三、Linux系统调用函数 fork()、wait()、exec()1. fork()&#xff1a;创建子进程2. wait()&#xff1a;等待子进程状态改变3. exec()&#xff1a;替换…