ARM汇编[1] 打印格式化字符串(printf
文章目录
- 写在前面
- 关键知识
- 简单加减乘除
- 函数调用和循环
- 系统调用
- 栈的使用
- GDB调试
- 示例代码
写在前面
如果您对ARM汇编还一无所知的话请先参考ARM汇编hello world
本篇不会广泛详细的列举各种指令,仍然只讲解最关键的部分,然后使用他们来完成一个汇编程序
关键知识
简单加减乘除
加
add x0, x1, x2
x0 = x1 + x2
减
sub x0, x1, x2
x0 = x1 - x2
乘
mul x1, x1, x0
x1 = x1 × x0,保存结果的低64位
除
sdiv x0, x1, x2
x0 = x1 / x2,保存结果的商
msub x3, x0, x2, x1
x3=x1-(x0 × x2),计算上述除法指令的余数
函数调用和循环
以下面这段计算字符串长度的程序为例
.datastrr: .string "hello~"strlen:stp x29,x30,[sp, -16]!mov x10, 0 // use x10 as counterstrlen_loop: // compare if cur byte is \0ldrb w9, [x0, x10]cmp w9, 0beq strlen_lendadd x10, x10, 1b strlen_loop // enter next round loopstrlen_lend:mov x0, x10ldp x29,x30,[sp], 16ret _start:ldr x0, =strrbl strlen
(上述代码片段并不完整,仅做说明使用)
x29 帧指针寄存器
x30 下一条指令寄存器
sp 栈指针寄存器
执行前先将x29和x30寄存器保存在sp,sp+7 . sp+8,sp+15的地方,并将sp的值减去一些以用作栈空间保存临时变量
结束的时候再从栈中恢复
x30寄存器保存的是下一条指令的地址,在ret执行的时候要用到
如果只是普通的调用这一个函数那即使不保存也不会出问题,但是如果这个函数内又调用了其他函数,那么这个x30寄存器就会指向错误的地址导致永远陷在这个函数中。(bus error)
函数调用和循环实际上都是跳转类指令
上述代码片段使用了bl、b和beq指令
bl指令:跳转到指定的地址执行下一条指令,并将跳转前的下一条指令地址保存在x30寄存器中,在ret的时候恢复(ret伪指令实际上是bl x30)
b指令:和bl一样但不保存x30,也就是说如果用b指令调用函数那结束的时候跳不回来
beq指令:判断标志位进行跳转的b指令,beq是相等时跳转
子函数调用的时候要记得把x9、x10…这些通用寄存器压栈保存,调用完再恢复
系统调用
ARM汇编hello world
这里已经讲过,本篇不再赘述
栈的使用
暂时没时间写,,看下示例程序吧,都写了注释的,有空的话我补一下
GDB调试
GDB调试在汇编中是必不可少的,学习汇编语言3天比我用c语言写3个月代码出的段错误都多,,
c语言还可以靠printf定位,汇编又没有,,
参考AT&T汇编的GDB调试这一节,用GDB调试的操作都是一样的
示例代码
实现类似c语言中printf函数的功能
用4个子函数实现
strlen:计算字符串长度
numlen:计算数字长度
numtos:将8位长度以内的数字转成ASCII码的字符串格式
prints:实现了能在格式化字符串中拼接打印一个正数的功能
root@arco-arm:/home/arco/as/prints# cat prints.s
.datastrr: .string "ret=%d\n"
.text.global strlen.global numlen.global numtos.global prints.global _start// p1: source string
// ret: length of string
strlen:stp x29,x30,[sp, -16]!mov x10, 0 // use x10 as counterstrlen_loop: // compare if cur byte is \0ldrb w9, [x0, x10]cmp w9, 0beq strlen_lendadd x10, x10, 1b strlen_loop // enter next round loopstrlen_lend:mov x0, x10ldp x29,x30,[sp], 16ret// p1: source number
// p2: 10/16
// ret: length of number
numlen:stp x29,x30,[sp, -16]!mov x12, 0 // use x12 store lengthnumlen_loop:sdiv x9, x0, x1 // use x9 cache quotientmsub x10, x9, x1, x0 // (x10=x0-(x9*x1))use x10 cache remainderadd x11, x9, x10cmp x11, 0beq numlen_lendadd x12, x12, 1 // length+1mov x0, x9 // use quotient as new dividendb numlen_loop // enter next round loopnumlen_lend:mov x0, x12 // copy the value from x12 to x0 as resultldp x29,x30,[sp], 16ret// p1: source number
// p2: 10/16
// ret: string format number
numtos:stp x29,x30,[sp, -32]! // save stack pointerstr x0, [sp, 16] // save origin num in stackbl numlen // call numlenmov x11, x0 // use x11 store num lengthldr x0, [sp, 16] // restore origin num from stackmov x12, 0 // use x12 as counteradd x13, x11, 15 // use x13 cache stack position(sp+16~16+len)numtos_loop:sdiv x9, x0, x1 // (x9=x0/x1)use x9 cache quotientmsub x10, x9, x1, x0 // (x10=x0-(x9*x1))use x10 cache remainderadd x10, x10, 0x30 // add '0'// sp+ :// sp+17:2// sp+16:1strb w10, [sp, x13] // store 1 byte to stack sub x13, x13, 1 // next byte position(from stack high to low, num l2hadd x12, x12, 1 // counter++cmp x11, x12 // judge if calculate overmov x0, x9 // use quotient as dividendbeq numtos_lendb numtos_loopnumtos_lend:ldr x0, [sp, 16] // copy stack value to x0ldp x29,x30,[sp],32 // restore stackret// p1: format string
// p2: target number
prints:stp x29,x30,[sp,-64]!mov x9, 0 // use x9 as counterstr x0, [sp, 16] // save format string addrstr x1, [sp, 24] // save target numberprints_loop:ldr x0, [sp, 16] // restore format string addrldrb w10, [x0, x9] // read 1 bytecmp w10, 0 // judge if overbeq prints_lendcmp w10, 0x25 // judge if %beq prints_valueprints_value_over:// counter point to next char ldr x1, [sp, 16] // restore str addradd x1, x1, x9 // next char addr is origin+offsetmov x0, 1mov x2, 1mov x8, 64svc #0add x9, x9, 1b prints_loopprints_lend:ldp x29,x30,[sp], 64ret
prints_value:add x9, x9, 1 // counter+1, jump %ldrb w10, [x0, x9] // read the byte after %cmp x10, 0x64 // case %dbeq prints_decb prints_value_over // if no matches, jump back and print next char
prints_dec:str x9, [sp, 40] // save x9 (counterldr x0, [sp, 24] // restore target numbermov x1, 10bl numlenmov x2, x0str x2, [sp, 32] // save the length of target numberldr x0, [sp, 24]mov x1, 10bl numtosldr x9, [sp, 40] // restore x9str x0, [sp, 24] // store str format num in sp+24mov x0, 1 // stdoutmov x1, spadd x1, x1, 24 // the address of str format numldr x2, [sp, 32] // out lengthmov x8, 64svc #0add x9, x9, 1 // to next charb prints_value_over_start:ldr x0, =strrmov x1, 123bl prints# exitmov x8, #93// use return of numlen as returnsvc #0相关文章:
ARM汇编[1] 打印格式化字符串(printf
文章目录 写在前面关键知识简单加减乘除函数调用和循环系统调用栈的使用 GDB调试示例代码 写在前面 如果您对ARM汇编还一无所知的话请先参考ARM汇编hello world 本篇不会广泛详细的列举各种指令,仍然只讲解最关键的部分,然后使用他们来完成一个汇编程序…...
Java 集合、迭代器
Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queu…...
在 Docker 中启动 ROS2 里的 rivz2 和 rqt 出现错误的解决方法
1. 出现错误: 运行 ros2 run rivz2 rivz2 ,报错如下 : No protocol specified qt.qpa.xcb: could not connect to display :1 qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was f…...
使用securecrt+xming通过x11访问ubuntu可视化程序
windows使用securecrtxming通过x11访问ubuntu可视化程序 windows机器IP:192.168.9.133 ubuntu-desktop20.04机器IP:192.168.9.190 windows下载xming并安装 按照图修改xming配置 开始->xming->Xlaunch 完成xming会在右下角后台运行 windows在…...
红队打靶练习:HEALTHCARE: 1
目录 信息收集 1、arp 2、nmap 3、nikto 4、whatweb 目录探测 1、gobuster 2、dirsearch WEB web信息收集 gobuster cms sqlmap 爆库 爆表 爆列 爆字段 FTP 提权 信息收集 本地提权 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Inte…...
Java IO:概念和分类总结
前言 大家好,我是chowley,刚看完Java IO方面内容,特此总结一下。 Java IO Java IO(输入输出)是Java编程中用于处理输入和输出的API。它提供了一套丰富的类和方法,用于读取和写入数据到不同的设备、文件和…...
【Linux】基本命令(下)
目录 head指令 && tail指令 head指令 tail指令 find指令 grep指令 zip/unzip指令 tar指令 时间相关的指令 date显示 1.在显示方面,使用者可以设定欲显示的格式,格式设定为一个加号后接数个标记,其中常用的标记列表如下&…...
腾讯云游戏联机服务器配置价格表,4核16G/8核32G/4核32G/16核64G
2024年更新腾讯云游戏联机服务器配置价格表,可用于搭建幻兽帕鲁、雾锁王国等游戏服务器,游戏服务器配置可选4核16G12M、8核32G22M、4核32G10M、16核64G35M、4核16G14M等配置,可以选择轻量应用服务器和云服务器CVM内存型MA3或标准型SA2实例&am…...
面试经典150题——长度最小的子数组
"In the midst of winter, I found there was, within me, an invincible summer." - Albert Camus 1. 题目描述 2. 题目分析与解析 首先理解题意,题目要求我们找到一个长度最小的 连续子数组 满足他们的和大于target,需要返回的是子数组的…...
业务流程
一、需求分析和设计: 在项目启动阶段,需要与业务人员和产品经理充分沟通,了解业务需求,并根据需求进行系统设计和数据库设计。这一阶段的输出通常是需求文档、系统架构设计、数据库设计等。 1.需求文档 需求文档是一份非常重要…...
ChatGPT Plus如何升级?信用卡付款失败怎么办?如何使用信用卡升级 ChatGPT Plus?
ChatGPT Plus是OpenAI提供的一种高级服务,它相较于标准版本,提供了更快的响应速度、更强大的功能,并且用户可以优先体验到新推出的功能。 尽管许多用户愿意支付 20 美元的月费来订阅 GPT-4,但在实际支付过程中,特别是…...
Spring 如何配置 bean (XML 方式)
请直接看原文:Spring 如何配置 bean (XML 方式)_spring 在哪配置bean 文件-CSDN博客 -------------------------------------------------------------------------------------------------------------------------------- Java Bean 如何配置配置到 spring 容器中 基于 XM…...
揭秘外观模式:简化复杂系统的关键设计策略
前言 外观模式(Facade Pattern)是一种结构型设计模式,它隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口。这种类型的设计模式向现有的系统添加一个接口,来隐藏系统的复杂性。这种模式涉及到一个单一的类…...
Nginx 命令(Ubuntu)
常用命令: 1.查看错误日志: sudo vim /var/log/nginx/error.log 2.重新加载 nignx sudo systemctl reload nginx 3.立即停止Nginx服务。如果Nginx正在运行,它将被终止 sudo systemctl stop nginx 4. 禁止Nginx服务在系统重启时自动启…...
从github上拉取项目到pycharm中
有两种方法,方法一较为简单,方法二用到了git bash,推荐方法一 目录 有两种方法,方法一较为简单,方法二用到了git bash,推荐方法一方法一:方法二: 方法一: 在github上复制…...
python从入门到精通(十八):python爬虫的练习案列集合
python爬虫的练习 1.爬取天气网的北京城市历史天气数据1.1 第一种使用面向对象OOP编写爬虫1.2 第二种使用面向过程函数编写爬虫 1.爬取天气网的北京城市历史天气数据 1.1 第一种使用面向对象OOP编写爬虫 import re import requests from bs4 import BeautifulSoup import xlw…...
2.12作业
第一题:段错误。 第二题:hello world 第三题:hello 第四题:world 第五题: a: int a; b: int*a; c: int a0;int *p&a;int **q&p; d: int a[10]; e: int *a[10]; …...
树莓派4B(Raspberry Pi 4B) 使用docker搭建单机版nacos
树莓派4B(Raspberry Pi 4B) 使用docker搭建单机版nacos ⚠️ 由于树莓派上的芯片是ARM架构,而官方推出的docker镜像不适用于ARM架构,所以想用树莓派搭建最新版的Nacos服务的小伙伴们可以忽略我这篇文章了。本文基于nacos 2.0.4&am…...
C++入门学习(二十七)跳转语句—continue语句
当在循环中遇到continue语句时,它会跳过当前迭代剩余的代码块,并立即开始下一次迭代。这意味着continue语句用于跳过循环中特定的执行步骤,而不是完全终止循环。 直接看一下下面的代码更清晰: 与上一节的break语句可以做一下对比…...
JPEG图像格式加速神经网络训练--使用DCT训练CNN
JPEG图像格式加速神经网络训练 JPEG图像格式加速神经网络训练工作原理DCT系数与JPEG直接利用DCT系数阶段 1: 数据准备步骤 1: 读取JPEG文件结构步骤 2: 提取量化表和Huffman表步骤 3: 解析图像数据步骤 4: 反量化步骤 5: 获取DCT系数 阶段 2: 输入处理预处理 1: 正规化…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
