汇编(实现C语言程序的调用)

news/2024/9/20 4:31:22/ 标签: 汇编, c语言, 开发语言

一、ARM汇编指令

  1. mov: 将一个值或寄存器的内容移动到另一个寄存器中。这个指令可以用来赋值。

    示例:mov r0, #5 // 将立即数 5 移动到寄存器 r0

  2. add: 执行加法操作,将两个操作数相加,并将结果存储在目标寄存器中。

    示例:add r0, r1, r2 // 将 r1 和 r2 的值相加,并将结果存储在 r0 中

  3. sub: 执行减法操作,从一个寄存器的值中减去另一个寄存器的值,并将结果存储在目标寄存器中。

    示例:sub r0, r1, r2 // 计算 r1 - r2 的值,并将结果存储在 r0 中

  4. ldr: 从内存中加载数据到寄存器中。

    示例:ldr r0, [r1] // 从 r1 指向的地址加载数据到 r0 中

  5. bic: 对两个操作数执行按位清除运算,保留第一个操作数中的位,而将第二个操作数中的位清零。

    示例:bic r0, r1, r2 // 清除 r1 中与 r2 中相同的位,将结果存储在 r0 中

  6. orr: 对两个操作数执行按位或运算。

    示例:orr r0, r1, r2 // 将 r1 和 r2 的位进行按位或运算,结果存储在 r0 中

  7. cmp: 比较两个寄存器中的值,设置相应的标志位(如零标志、负标志等),但不存储结果。

    示例:cmp r0, r1 // 比较 r0 和 r1 的值

  8. stmfd: 将多个寄存器的内容存入内存,按全降序存储,通常用于保存寄存器状态。

    示例:stmfd sp!, {r0, r1, r2} // 将 r0, r1, r2 存储到栈中

  9. ldmfd: 从内存中加载多个寄存器的内容,按全升序恢复寄存器状态。

    示例:ldmfd sp!, {r0, r1, r2} // 从栈中加载 r0, r1, r2 的值

二、跳转语句

  1. b: 无条件跳转指令,跳转到指定的标签或地址。这是ARM汇编中最常用的跳转指令。

    示例:b label // 跳转到名为 label 的位置

  2. bl: 带链接的跳转,除了跳转到指定地址外,还将返回地址(下一条指令的地址)保存到链接寄存器(LR 或 r14)中。常用于子程序调用。

    示例:bl function // 跳转到 function,并将返回地址存储在 LR 中

  3. bx: 通过指定的寄存器地址跳转,并且可以根据寄存器的最低位设置处理器的状态(如进入 ARM 或 Thumb 状态)。它通常用于从子程序返回。

    示例:bx r0 // 跳转到 r0 寄存器中存储的地址

栈指针寄存器

  • SP(栈指针寄存器): SP 寄存器用于指向当前栈的顶部。栈通常用于存储局部变量、保存返回地址等。当使用 stmfd 和 ldmfd 指令时,stack pointer (SP) 寄存器可用于管理函数调用和返回。

CPSR 寄存器相关指令

  1. mrs: 从 CPSR(当前程序状态寄存器)读取数据。当需要获取当前状态或标志位时,使用此指令。

    示例:mrs r0, cpsr // 将 CPSR 的值加载到 r0 中

  2. msr: 设置 CPSR 的某些位。这可以用于改变处理器的状态或控制特权级别。

    示例:msr cpsr_c, r0 // 将 r0 的内容写入 CPSR 中的控制位

三、汇编

preserve8               ; 保留8字节对齐  
area reset, code, readonly ; 定义一个名为“reset”的只读代码区域  
code32                  ; 设定代码为32位  
entry                   ; 定义入口点  b start                 ; 跳转到 start 标签,开始程序执行  
ldr pc, =do_undifined   ; 将 do_undifined 的地址加载到程序计数器(PC),设置未定义指令处理  
ldr pc, =do_swi        ; 将 do_swi 的地址加载到 PC,设置软件中断处理  
ldr pc, =do_p_abort    ; 将 do_p_abort 的地址加载到 PC,设置预取中止处理  
ldr pc, =do_d_abort    ; 将 do_d_abort 的地址加载到 PC,设置数据中止处理  
nop                     ; 空操作,通常用于填充或延迟  
ldr pc, =do_irq        ; 将 do_irq 的地址加载到 PC,设置外部中断处理  
ldr pc, =do_fiq        ; 将 do_fiq 的地址加载到 PC,设置快速中断处理  do_fiq                  ; 快速中断处理程序  b do_fiq              ; 无限循环,等待快速中断  do_irq                  ; 外部中断处理程序  import irq_handler    ; 导入 irq_handler 函数  sub lr, lr, #4        ; 将链接寄存器(LR)减去4,以调整返回地址  stmfd sp!, {r0-r12, lr} ; 将 r0-r12 和 LR 保存到栈中,进行现场保护  bl irq_handler        ; 调用中断处理程序  ldmfd sp!, {r0-r12, pc}^ ; 恢复寄存器并返回  do_d_abort              ; 数据中止处理程序  b do_d_abort          ; 无限循环,等待数据中止  do_p_abort              ; 预取中止处理程序  b do_p_abort          ; 无限循环,等待预取中止  do_swi                  ; 软件中断处理程序  import swi_handler     ; 导入 swi_handler 函数  stmfd sp!, {r0-r12, lr} ; 保存 r0-r12 和 LR 到栈中  bl swi_handler        ;  调用软件中断处理程序  ldmfd sp!, {r0-r12, pc}^ ; 恢复寄存器并返回  do_undifined            ; 未定义指令处理程序  b do_undifined        ; 无限循环,等待未定义指令  start                   ; 程序启动点  ldr sp, =0x40001000  ; 将栈指针(SP)初始化为指定地址  mrs r0, cpsr          ; 读取当前程序状态寄存器(CPSR)  bic r0, r0, #0x1F     ; 清除 CPSR 中的模式位  orr r0, r0, #0x12    ; 设置 CPSR 进入 SVC 模式  bic r0, #(1 << 7)     ; 清除 CPSR 中的 F 标志位  msr cpsr_c, r0       ; 更新 CPSR  ldr r0, =0x40001000  ; 将地址 0x40001000 加载到 r0   sub r0, r0, #1024    ; 计算栈顶地址  mov sp, r0           ; 设置栈指针 SP  mrs r0, cpsr          ; 读取当前 CPSR  bic r0, r0, #0x1F     ; 清除模式位  orr r0, r0, #0x10    ; 设置 CPSR 进入 IRQ 模式  msr cpsr_c, r0       ; 更新 CPSR  ldr r0, =0x40001000  ; 将地址 0x40001000 加载到 r0  sub r0, r0, #2048    ; 计算新的栈顶地址  mov sp, r0           ; 设置栈指针 SP  import main           ; 导入 main 函数  b main               ; 跳转到 main 函数  asm_fn                  ; 汇编函数的标签  export asm_fn         ; 导出 asm_fn 函数  swi #7                ; 触发软件中断,调用系统服务  bx lr                 ; 返回到调用者  finished                ; 完成标签  b finished            ; 无限循环,等待程序结束  end                    ; 汇编代码的结束标志


http://www.ppmy.cn/news/1527890.html

相关文章

malloc函数内存分配原理

malloc 是一个库函数&#xff0c;在<stdlib.h> 头文件中,是在程序的运行时库&#xff08;Runtime Library&#xff09;中实现的。这个函数主要用于在程序运行期间动态地分配内存。当在 C 语言程序中使用 malloc 时&#xff0c;实际上是在调用运行时库提供的一个函数&…

jmeter 录制APP脚本

一、手机 1、修改网络 代理选择手动→填写服务器主机名&#xff08;电脑IP&#xff0c;如&#xff1a;192.1xx.x.xx&#xff09;→服务器端口&#xff08;任意未被占用端口&#xff0c;如&#xff1a;8888&#xff09; 2、安装证书 手机浏览器访问服务器主机名:服务器端口&a…

linux 解压缩

1、tar命令 # 压缩文件 file1 和目录 dir2 到 test.tar.gz tar -zcvf test.tar.gz file1 dir2 # 解压 test.tar.gz&#xff08;将 c 换成 x 即可&#xff09; tar -zxvf test.tar.gz # 列出压缩文件的内容 tar -ztvf test.tar.gz 释义&#xff1a;-z : 使用 gzip 来压缩和解压…

GPT对话知识库——串口通信的数据的组成?起始位是高电平还是低电平?如何用代码在 FreeRTOS 中实现串口通信吗?如何处理串口通信中的数据帧校验吗?

目录 1&#xff0c;问&#xff1a; 1&#xff0c;答&#xff1a; 串口数据的组成 串口数据传输帧的完整结构 起始位的电平状态&#xff1a;低电平 举例&#xff1a;UART数据传输的例子 适用场景 总结 2&#xff0c;问&#xff1a; 2&#xff0c;答&#xff1a; a. 如…

滚雪球学SpringCloud[4.2讲]: Zuul:Netflix API Gateway详解

全文目录&#xff1a; 前言4.2 Zuul&#xff1a;Netflix API GatewayZuul的基础配置与使用引入Zuul依赖启用Zuul配置路由规则 Zuul的过滤器机制编写自定义过滤器 与Spring Security的集成配置Spring Security结合Zuul过滤器进行认证 实例案例&#xff1a;使用Zuul保护微服务 预…

【软考】数据字典(DD)

目录 1. 说明2. 数据字典的内容2.1 说明2.2 数据流条目2.3 数据存储条目2.4 数据项条目2.5 基本加工条目 3. 数据词典管理4. 加工逻辑的描述4.1 说明4.2 结构化语言4.3 判定表4.3 判定树 5. 例题5.1 例题1 1. 说明 1.数据流图描述了系统的分解&#xff0c;但没有对图中各成分进…

七种d3dcompiler_47.dll缺失怎么修复的方法,教你轻松解决d3dcompiler_47.dll缺失!

d3dcompiler_47.dll是 DirectX 的一部分&#xff0c;用于编译 Direct3D 着色器。如果这个文件缺失或损坏&#xff0c;可能会导致某些游戏或应用程序无法正常运行。以下是七种修复d3dcompiler_47.dll缺失问题的方法&#xff0c;教你轻松解决d3dcompiler_47.dll缺失&#xff01; …

BARTBERT

BART和BERT都是基于Transformer架构的预训练语言模型。 模型架构&#xff1a; BERT (Bidirectional Encoder Representations from Transformers) 主要是一个编码器&#xff08;Encoder&#xff09;模型&#xff0c;它使用了Transformer的编码器部分来处理输入的文本&#xff0…

Kotlin cancel CoroutineScope.launch的任务后仍运行

Kotlin cancel CoroutineScope.launch的任务后仍运行 import kotlinx.coroutines.*fun main() {runBlocking {val coroutineScope CoroutineScope(Dispatchers.IO)val job coroutineScope.launch {var i 0while (i < Int.MAX_VALUE) {iprintln(i)}}// 2ms 取消协程delay(…

利士策分享,赚钱与体重:一场关于生活平衡的微妙探索

利士策分享&#xff0c;赚钱与体重&#xff1a;一场关于生活平衡的微妙探索 在当今社会&#xff0c;赚钱与体重&#xff0c;这两个看似风马牛不相及的概念&#xff0c; 却在无形中交织着人们的生活轨迹。 它们不仅仅是数字上的增减&#xff0c;更是个人选择、生活方式乃至心理…

docker容器中的内存占用高的问题分析

文章目录 问题描述原因分析分析1分析2验证猜想 结论和经验 问题描述 运维新增对某服务的监控后发现&#xff1a;内存不断上涨的现象。进一步确认&#xff0c;是因为有多个导出日志操作导致的内存上涨问题。 进一步的测试得出的结果是&#xff1a;容器刚启动是占用内存约为50M…

智能负载均衡:分布式缓存的高效能解决方案

在当今快速发展的互联网时代&#xff0c;分布式缓存成为了提升网站性能和用户体验的关键技术。本文将深入探讨负载均衡算法在分布式缓存中的应用&#xff0c;分析各种算法的优缺点&#xff0c;并提供选择最佳算法的指导。通过实际案例&#xff0c;我们将展示如何通过智能的负载…

用Kimi输出流程图

1.输入 我希望设计一个ERP系统&#xff0c;请帮我简单列一个流程图&#xff0c;用mermaid输出2.输出

MySQL高级功能-窗口函数

背景 最近遇到需求&#xff0c;需要对数据进行分组排序并获取每组数据的前三名。 一般涉及到分组&#xff0c;第一时间就是想到使用group by对数据进行分组&#xff0c;但这样分组&#xff0c;到最后其实只能获取到每组数据中的一条记录。 在需要获取每组里面的多条记录的时候…

【笔记】枚举

文章目录 枚举的概念枚举步骤例题&#xff1a;百鸡百钱方案1方案二方案三 例题 枚举的概念 枚举&#xff1a;逐个尝试所有可能的方案。 先把问题划分成一系列离散的状态&#xff0c;然后遍历这些状态来求解问题。 比如求3x5y10的正整数解有多少&#xff0c;把x∈[0&#xff…

傅里叶变换的基本性质和有关定理

一、傅里叶变换的基本性质 1.1 线性性质 若 则 其中:a,b是常数 函数线性组合的傅里叶变换等于歌函数傅里叶变换的相应组合。 1.2 对称性 若 则 关于傅里叶变换的对称性还有 虚、实、奇、偶函数的傅里叶变换性质: 1.3 迭次傅里叶变换 对f(x,y)连续两次做二维傅里叶变换…

【笔记篇】Davinci Configurator TcpIp模块

目录 1 简介1.1 架构概览2 功能描述2.1 特性2.2 TCP/IP协议栈2.2.1 IPv62.2.2 IPv42.3 初始化2.3 状态机2.4 主函数2.5 故障处理3 集成3.1 静态文件3.2 动态文件4 API描述5 配置5.1 Socket 拥有者配置5.1.1 `<Up>_CopyTxData` callback5.2 单播地址分配方法5.2.1 IPv4 单…

【GeekBand】C++设计模式笔记1_介绍

1. 课程目标 理解松耦合设计思想掌握面向对象设计原则掌握重构技法改善设计掌握GOF核心设计模式 2. 什么是设计模式 目标&#xff1a;复用&#xff0c;以不变应万变 3. GOF设计模式 4. 从面向对象谈起 5. 深入理解面向对象 向下&#xff1a;深入理解三大面向对象机制 封装&…

Gitlab学习(009 gitlab冲突提交)

尚硅谷2024最新Git企业实战教程&#xff0c;全方位学习git与gitlab 总时长 5:42:00 共40P 此文章包含第30p-第p34的内容 文章目录 冲突提交不同人修改不同文件不同人修改同文件的不同区域不同人修改同文件的相同区域 同时变更文件名和文件内容gitLab功能拓展code review代码复…

Vue3: setup语法糖

一. setup语法糖 在 Vue 3 中&#xff0c;setup 语法糖是一种简化组件内部状态和方法管理的特性。它允许你将组件的逻辑直接编写在组件的定义中&#xff0c;而不是像 Vue 2 那样需要在 methods 和 data 属性中管理。setup 语法糖基于 ES6 的类的静态方法&#xff0c;允许你更灵…