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: 正规化…...

【代码】Processing笔触手写板笔刷代码合集
代码来源于openprocessing,考虑到国内不是很好访问,我把我找到的比较好的搬运过来! 合集 参考:https://openprocessing.org/sketch/793375 https://github.com/SourceOf0-HTML/processing-p5.js/tree/master 这个可以体验6种笔触…...

Junit常用注解
注解是方法的“标签” 说明每个方法的“职责” Q:总共有那些注解? 参见官方的API文档 0.常用主机及其特点 BeforeClass 只会执行一次必须用static修饰常用来初始化测试需要的变量 Before 会执行多次(只要写一次)在每个Test执行执行之前执行可以和…...

【机器学习】支持向量机(SVM)
支持向量机(SVM) 1 背景信息 分类算法回顾 决策树 样本的属性非数值 目标函数是离散的 贝叶斯学习 样本的属性可以是数值或非数值目标函数是连续的(概率) K-近邻 样本是空间(例如欧氏空间)中的点目标函…...

C语言指针全解
1.什么是指针: 指针是存放地址的地方,是内存中最小单元的地址(编号),内存被分为一个个小的单元格,每一格有一个字节。比如说int a0;a会占据四个字节的大小,每个字节对应单元格都有自…...

rtt设备io框架面向对象学习-看门狗设备
1.看门狗设备基类 / components / drivers / include / drivers /下的watchdog.h 定义了如下看门狗设备基类 struct rt_watchdog_device { struct rt_device parent; const struct rt_watchdog_ops *ops; }; 看门狗设备基类的方法定义如下 struct rt_watchdog_ops { rt_err_…...

加固平板电脑丨三防智能平板丨工业加固平板丨智能城市管理
随着智能城市的不断发展,人们对于城市管理的要求也在不断提高,这就需要高效、智能的城市管理平台来实现。而三防平板就是一款可以满足这一需求的智能设备。 三防平板是一种集防水、防尘、防摔于一体的智能平板电脑,它可以在复杂的环境下稳定运…...

Redis的配置文件
目录 前言: 一、 Units 二、 INCLUDES 三、 NETWORK 3.1 bind 3.2 protected-mode 3.3 port 3.4 tcp-backlog 3.5 timeout 3.6 tcp-keepalive 3.7 示例演示 四、 GENERAL 4.1 daemonize 4.2 pidfile 4.3 loglevel 4.4 logfile 4.5 databases 五、…...

懒人精灵 之 Lua 捕获 json解析异常 ,造成的脚本停止.
Time: 2024年2月8日20:21:17 by:MemoryErHero 1 异常代码 Expected value but found T_END at character 12 异常代码 Expected value but found T_OBJ_END at character 223 处理方案 - 正确 json 示范 while true do--Expected value but found T_END at character 1--Ex…...

Python 列表操作详解
Python 是一种流行的编程语言,它以其简洁的语法和强大的功能而闻名。在 Python 中,列表是一种常用的数据结构,它可以包含任意类型的元素,并且可以随时添加或删除元素。在这篇文章中,我们将详细介绍 Python 列表的一些常…...

【Jenkins】Jenkins关闭Jenkins关闭、重启
目录 一、Jenkins关闭、重启 二、Jenkins服务的启动、停止方法。 一、Jenkins关闭、重启 1.关闭Jenkins 只需要在访问jenkins服务器的网址url地址后加上exit,关闭Jenkins服务。 例如:http://localhost:8081/exit 2.重启Jenkies 只有在Jenkins服务启动…...