QEMU用户模式测试AARCH64程序
QEMU的两种模式
QEMU(快速模拟器)是一个开源的机器模拟器和虚拟化器,它能够模拟多种处理器架构,并且可以在不同平台上运行。QEMU 支持两种模式:用户模式和系统模式。
- 用户模式(User Mode):
- 用户模式下的 QEMU 仅模拟用户空间的二进制执行环境,不模拟底层硬件。
- 这种模式下,QEMU 可以运行不同架构编译的二进制程序,而不需要这些程序与宿主机的架构相匹配。
- 用户模式通常用于测试和运行不同架构的应用程序,或者在不支持特定硬件架构的系统上运行程序。
- 用户模式不需要硬件虚拟化支持,因为它不模拟硬件。
- 系统模式(System Mode):
- 系统模式下的 QEMU 模拟整个计算机系统,包括 CPU、内存、硬盘、网络接口等硬件设备。
- 这种模式下,QEMU 可以运行完整的操作系统镜像,允许用户安装和运行完整的操作系统。
- 系统模式需要更多的资源,并且可能需要硬件虚拟化支持,以提高性能和安全性。
- 系统模式允许用户进行更全面的测试,包括操作系统级别的测试和硬件兼容性测试。
- 在系统模式下,QEMU 还可以使用不同的后端来提高性能,例如使用 KVM(Kernel-based Virtual Machine)在 Linux 系统上进行硬件辅助虚拟化。KVM 可以将 QEMU 转换为一个全功能的虚拟机监控器,提供接近原生硬件的性能。
要启动 QEMU 并使用用户模式或系统模式,你需要使用不同的命令行参数。例如:
用户模式:qemu-<arch> -cpu <cpu-type> -L <path-to-libraries> <program-to-run>
系统模式:qemu-system-<arch> -m <memory-size> -hda <disk-image>
其中 <arch> 是你想要模拟的架构,比如aarch64,<cpu-type> 是特定的 CPU 类型,<path-to-libraries> 是库文件的路径,<program-to-run> 是你想要运行的程序,<memory-size> 是分配给虚拟机的内存大小,<disk-image> 是虚拟硬盘镜像的路径。
QEMU 是一个非常灵活的工具,可以根据需要进行配置和扩展,以满足不同的模拟和虚拟化需求。
用户模式的安装
简单的执行如下命令就可以安装用户模式:
sudo apt-get update
sudo apt-get install qemu-user qemu-user-static gdb-multiarch build-essential gcc-aarch64-linux-gnu
用户模式C程序的测试
编写一个简单的C程序:
#include <stdio.h>int main(void) { return printf("Hello AARCH64!\n");
}
使用aarch64的编译器进行静态的交叉编译:
aarch64-linux-gnu-gcc -static -o hello64 hello.c
编译后使用file命令确认一下编译产生的事aarch64架构文件。
developer@ecs-cloud-host-ubuntu-img-make:~$ file hello64
hello64: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=c6209c6d4f0f2ec56fc1e9fe2443c34009ad60d5, for GNU/Linux 3.7.0, not stripped
如果没有安装QEMU用户模式程序,直接运行该程序会报告错误:
bash: ./hello64: cannot execute binary file: Exec format error
安装了QEMU用户模式之后,直接运行程序就可以得到正确的输出了。这是因为系统内有qemu-user-static,它支持了其他架构程序的直接运行。
developer@ecs-cloud-host-ubuntu-img-make:~$ ./hello64
Hello AARCH64!
也可以不使用static编译,比如:
aarch64-linux-gnu-gcc -o hello64dyn hello.c
不过不能直接运行hello64dyn这个程序,会报告错误:
developer@ecs-cloud-host-ubuntu-img-make:~$ ./hello64dyn
aarch64-binfmt-P: Could not open '/lib/ld-linux-aarch64.so.1': No such file or directory
这是需要使用qemu-user了:
developer@ecs-cloud-host-ubuntu-img-make:~$ qemu-aarch64 -L /usr/aarch64-linux-gnu ./hello64dyn
Hello AARCH64!
用户模式汇编程序的测试(调用C库)
准备一个简单的汇编程序hello.S
.section .text.global mainmain:
// Call puts and return stp fp, lr, [sp, #0x10]!mov fp, spadr x0, msgbl putsmov w0, wzrldp fp, lr, [sp], #0x10retmsg:.asciz "Hello Again!".align 2
这个程序里面调用了C语言的puts函数。
前两条指令是所谓的序言,SP 寄存器被调整,以便在可能的中断情况下保存数据,以便使用 puts 函数。
adr 指令将 x0 设置为字符串所在位置的内存地址。
'bl puts' 调用 puts 函数。它是一个 C 库函数,它将文本输出到控制台/终端。或者,可以使用 printf 代替。之所以使用 puts,是因为它对 CPU 来说更快,因为它不能接受所谓的字符串中的格式描述符。此外,puts 函数在控制台上自动加入换行。注意我们没有在 Hello Again 字符串中包含 "\n"。
'mov w0, wzr' 指令是给 CPU 一个零值,它将在退出程序时使用。稍后,CPU 将调用 C/C++ 退出函数来退出程序。每当你编写任何 .S(main:)类型的源文件时,最终的 ret 指令将使 CPU 结束程序并调用 C/C++ 退出函数。在 ret 指令之前,w0 应该总是设置为 0。
最后两条指令是所谓的尾声。基本上是序言的相反。
直接使用下面的语句去编译,C语言的编译器会自动处理汇编代码并进行库链接。
aarch64-linux-gnu-gcc -o hello hello.S
运行程序的方法和前面类似:
developer@ecs-cloud-host-ubuntu-img-make:~$ qemu-aarch64 -L /usr/aarch64-linux-gnu ./hello
Hello Again!
用户模式汇编程序的测试(调用系统调用)
我们也可以不使用C语言函数,直接使用QEMU模拟的系统调用。这和系统模式所模拟的裸机编程有所不同,系统模式是不提供任何系统调用的,你必须自己写串口输出代码或者使用编译好的BIOS文件。
下面是汇编代码:
.section .text.global _start_start:
// syscall write(int fd, const void *buf, size_t count)mov x0, #1 adr x1, msgmov x2, lenmov w8, #64 /*Syscall number for write for ARM64*/svc #0// syscall exit(int status)mov x0, #0mov w8, #93 /*Syscall number for exit for ARM64*/svc #0msg:.asciz "Hello World!\n"len = . - msg
QEMU 模拟所谓的系统调用。这些系统调用旨在模拟具有内置基本任务功能的计算机 BIOS。可以在程序中使用 svc 指令调用。在真正的硬件中,svc 指令将进入一个异常处理程序。在这个程序中,有代码(已经由程序早期编写)来处理 svc 的使用。
在 QEMU 中,这是完全不同的。你的程序在异常处理程序中写了什么并不重要。QEMU 将执行 svc 来模拟一个已经编写了某些指令的计算机 BIOS。简而言之,那里的例程在计算机 BIOS 中是通用的。因此,该例程接受某些参数以产生结果。你可以看出这是情况,因为在上述文件中,我们没有编写任何指令到任何异常处理程序。模拟系统调用的不好之处在于我们不能实际看到和调试 svc 异常。好的是,我们可以使用这些模拟器系统调用来执行基本任务。比如打印文本到控制台(终端),修改文件等。
系统调用 Write 会在控制台(终端)上打印消息。系统调用 Exit 退出程序。
有许多系统调用,每个系统调用都需要参数。在系统调用被“调用”(通过 svc 指令)之前,必须将正确的值放在正确的寄存器中。这种将正确的参数放在正确的寄存器中的概念被称为 ARM64 的调用约定。
代码中一些变量的解释:
- adr 设置 msg 标签所在位置的内存地址。
- msg: 是源文件中 Hello World 字符串所在的标签。字符串中的 "\n" 部分是你在控制台/终端输入新行时需要输入的。
- len = . - msg 这是用于计算字符串大小的汇编器指令。点(.)在这里代表这里。所以 '这里' 减去 msg 将设置字符串的字节量。
要运行程序,需要将其汇编成一个目标文件。然后使用链接器制作一个可执行文件。这可以通过以下两个终端命令完成..
aarch64-linux-gnu-as hello_world.s -o hello_world.o
aarch64-linux-gnu-ld hello_world.o -o hello_world
所以我们现在有一个可执行文件。我们可以用 QEMU 启动它:
qemu-aarch64 ./hello_world
得到如下输出:
developer@ecs-cloud-host-ubuntu-img-make:~$ qemu-aarch64 ./hello_world
Hello World!
因为安装了qemu-user-static,直接运行程序也是可以的。
参考文献
- Assembler, QEMU, GDB
- Running Arm Binaries on x86 with QEMU-User | Azeria Labs
相关文章:
QEMU用户模式测试AARCH64程序
QEMU的两种模式 QEMU(快速模拟器)是一个开源的机器模拟器和虚拟化器,它能够模拟多种处理器架构,并且可以在不同平台上运行。QEMU 支持两种模式:用户模式和系统模式。 用户模式(User Mode)&…...

机器学习(五) -- 监督学习(8) --神经网络2
机器学习系列文章目录及序言深度学习系列文章目录及序言 上篇:机器学习(五) -- 监督学习(8) --神经网络1 下篇: 前言 tips:标题前有“***”的内容为补充内容,是给好奇心重的宝宝看…...

物联网之PWM呼吸灯、脉冲、LEDC
MENU 前言原理硬件电路设计软件程序设计analogWrite()函数实现呼吸灯效果LEDC输出PWM信号 前言 学习制作呼吸灯,通过LED灯的亮度变化来验证PWM不同电压的输出。呼吸灯是指灯光在单片机的控制之下完成由亮到暗的逐渐变化,感觉好像是人在呼吸。 原理 脉冲宽…...

Python利用pyecharts实现数据可视化
小编会持续更新知识笔记,如果感兴趣可以三连支持。闲来无事,水文一篇,不过上手实践一下倒还是挺好玩的,这一块知识说不定以后真可以尝试拿来做数据库的报表显示。 有梦别怕苦,想赢别喊累。 目录 前言 JSON数据格式的…...

网恋照妖镜源码搭建教程
文章目录 前言创建网站1.打开网站设置 配置ssl2.要打开强制HTTPS,用宝塔免费的ssl证书即可,也可以使用其他证书,必须是与域名匹配的3.上传文件至根目录进行解压4.解压后,修改文件 sc.php 里面的内容5.其余探索 前言 前俩年很火的…...

STM32
(以下操作环境为Keil5和proteus8.9) 八种输入输出模式及他们的工作模式 分析如下 总线:总线提供了数据在不同组件(如处理器、内存、输入输出设备等)之间传输的路径,使数据能够快速、准确地在系统内流动。 …...

用手机做抢答器 低预算知识竞赛活动的选择
使用手机作为抢答器是低预算竞赛活动的一个理想选择。随着智能手机的普及,传统抢答器已经被手机抢答器所替代,这种转变不仅降低了成本,而且提供了更大的灵活性和便利性。通过手机扫码登录竞赛软件,参赛者可以直接在手机上进行抢答…...

ELK学习笔记(二)——使用K8S部署Kibana8.15.0
上篇文章我们完成了,ES的集群部署,如果还没有看过上篇文章的兄弟,可以去看看。 ELK学习笔记(一)——使用K8S部署ElasticSearch8.15.0集群 话不多说,接下来直接进入kibana的搭建 一、下载镜像 #1、下载官方…...
报错:CPU指令集的问题
bug描述 我在运行CMAQ中的icon时,遇到bug: Please verify that both the operating system and the processor support Intel(R) X87, CMOV, MMX, FXSAVE, SSE, SSE2, SSE3, SSSE3, SSE4_1, SSE4_2, POPCNT and AVX instructions.解决办法 经过查询&a…...

Type-C接口诱骗取电快充方案
Type-C XSP08Q 快充协议芯片是一种新型电源管理芯片,主要负责控制充电电流和电压等相关参数,从而实现快速充电功能。Type-C XSP08Q快充协议是在Type-C接口基础上,加入了XSP08Q协议芯片的支持,很大程度上提升了充电速度。 正常情况…...

图像白平衡
目录 效果 背景 什么是白平衡? 实现原理 将指定图色调调整为参考图色调主要流程 示例代码 效果 将图一效果转换为图二效果色调: 调整后,可实现色调对换 背景 现有两张图像,色调不一致,对于模型重建会有影响。因…...
SAP Business One 与无锡哲讯:携手共创企业数字化未来
在当今快速发展的商业世界中,企业的数字化转型已成为提升竞争力的关键。在众多的数字化解决方案中,SAP Business One 以其强大的功能和灵活性脱颖而出。与此同时,无锡哲讯智能科技有限公司作为专业的 SAP 系统服务提供商,为企业带…...

Unity Adressables 使用说明(五)在运行时使用 Addressables(Use Addressables at Runtime)
一旦你将 Addressable assets 组织到 groups 并构建到 AssetBundles 中,就需要在运行时加载、实例化和释放它们。 Addressables 使用引用计数系统来确保 assets 只在需要时保留在内存中。 Addressables 初始化 Addressables 系统在运行时第一次加载 Addressable …...
什么是死锁,如何解决?
什么是死锁? 在并发编程中,死锁是指两个或多个进程在竞争资源时,互相等待无法继续执行的状态。这种情况发生时,每个进程都在等待其他进程释放它们所需要的资源,但同时又不释放自己占有的资源,导致所有进程…...
借助ChatGPT三步,完成课题申报书中研究价值部分写作全攻略指南
大家好,感谢关注。我是七哥,一个在高校里不务正业,折腾学术科研AI实操的学术人。关于使用ChatGPT等AI学术科研的相关问题可以和作者七哥(yida985)交流,多多交流,相互成就,共同进步,为大家带来最酷最有效的智能AI学术科研写作攻略。 撰写申请书中的“本课题的学术价值…...

IDEA取消自动选择光标所在行
今天出现了一个怪事: 当我使用IDEA编写代码的时候,单击下一行或者上一行的时候,莫名其妙它会自己选中一行,导致我要么是回车代码直接没了,要么是代码直接给我搞错位了,还得按ctrlz返回,十分的恶…...

VUE2.0 elementUI el-input-number 数据更新,视图不更新——基础积累
今天遇到一个问题,是关于el-input-number组件的,发现数据明明已经更改了,但是页面上组件输入框中还是之前的值。 比如上方输入框中,我输入120.5,就会出现下面的诡异现象 回显此值是120.779,但是页面上输入…...

JS中this指向问题
首先,this的绑定和定义的位置无关,它的指向只和调用方式有关,this只有在运行时才知道指向谁。 一,默认绑定 默认绑定,也可以说是独立函数调用,这时this指向window。 function foo() {console.log(this) …...
大厂面试:小米嵌入式面试题大全及参考答案(130+道 12万长文)
Flink 架构介绍 Flink 是一个分布式流处理和批处理框架,具有高吞吐、低延迟、高可靠等特点。其架构主要由以下几个部分组成: 客户端(Client):负责将作业提交到集群,并与作业管理器进行交互,获取作业的状态信息。客户端可以是命令行工具、IDE 插件或者自定义的应用程序。…...
React 更新界面
文章目录 发现宝藏引入 useState声明和使用状态多个组件的状态管理解析代码 状态的局部性和性能优化结论 发现宝藏 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【宝藏入口】。 在 React 中ÿ…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...