blog.74ls74.org/2022/12/31/20221231_rpi_internals_assembly_the_good_parts_1/
阅读本文您不需要掌握的知识有
-
高深的操作系统理论
-
高深的计算机体系结构理论
-
高深的程序设计理论
阅读本文您需要具备
-
GNU工具链(make/GCC/LD) ★★☆☆☆
-
C语言 ★★☆☆☆
-
安装有raspbian的树莓派
阅读本文您可以得到什么
-
可以用汇编语言刷online judge
-
仍然无法做出让人振奋的东西,满足成就感
0. 历史
1985年,第一代arm处理器在Acorn诞生,此时arm指Acorn RISC Machine。
1990年,Acorn、VLSI和Apple联合成立了ARM公司,Advanced RISC Machine高级精简指令集机器。
新成立的公司决定公司的主要业务是设计并出售芯片的IP license,不做芯片制造和销售。夏普、德州仪器、三星成为他们第一批客户。发展到今天,intel、AMD、Qualcomm、broadcom、ZTE、Huawei等很多芯片巨头都是ARM的客户。ARM以及众多半导体IP设计公司一道设计出久经考验的IP block, 今天的芯片公司把处理器核心、内存控制器、外设、总线等IP像搭积木一样拼装在一起,从而在一块芯片上实现完整的嵌入式系统,大大提高了开发效率。而且因为ARM完善的软件生态,使芯片公司在软件适配方面节省了大量资金和人力。
1. 为什么学习arm汇编
当操作系统需要一些细粒度的操作时,c语言不够用。设置堆栈、保存和切换上下文、设置中断函数开关中断、系统调用软中断、虚拟内存、缓存管理,调用一些特殊系统指令、访问系统寄存器。当我们有这些需求,arm汇编是绕不过去的。
知道的太少,不懂的太多。一些新想法的实现中遇到的困难总是层峦叠嶂。我会尽量少的引入新的知识,语言精粹,为了拥有流畅的学习体验。待到勇攀高峰,一切就会拨云见日。
2. 树莓派arm汇编
arm汇编为了保持向后兼容性,越来越复杂,包含整型计算、thumb、64位的支持、数值计算相关。
arm32汇编是ARMv8-A之前架构所通用的汇编。本文以ARMv7-A为主,介绍arm32汇编的基础子集,包含整型等基础指令。我们首先要理清几个概念。
2.1 thumb
thumb指令集是arm32指令集的一个子集,指令长度16bit,它的指令和32位arm指令是对应的,这样设计的目的是为了实现更高的代码密度code density。有趣的是,处理器在执行thumb指令时会实时转换成32位arm指令,不会造成性能损失。
本文内容不会涉及thumb
2.2 arm64
从ARMv8-A架构开始,arm准备在A系列内核逐步放弃32位从而走上64位,使用全新设计的arm64指令集。第三代树莓派所搭载的soc是bcm2837,它的处理器内核Cortex-A53就是一款ARMv8-A架构处理器,支持arm64指令集。
本文内容不会涉及arm64
2.3 aarch32, aarch64
在ARMv8-A架构中有两个模式aarch32和aarch64,aarch32模式可以向后兼容,和arm32几乎完全兼容。
本文内容不会涉及aarch64
2.4 VFP, NEON
VFP, NEON都是arm32指令集的子集,包含浮点和向量计算等数学相关的指令。这些交给专业的人和工具吧!
https://developer.arm.com/documentation/den0018/a/Compiling-NEON-Instructions/NEON-libraries
本文内容不会涉及vfp和neon
硬件操作相关的内容会在下一篇章介绍。
arm处理器架构有很多变种,例如ARMv4T,ARMv5T,ARMv6等,arm32指令几乎与它们完全兼容。树莓派soc bcm2835的核心ARM1176JZFS是ARMv6架构。
不得不说兼容性带来了沉重的历史包袱,也带来繁荣的软件生态。就像intel划时代的x86处理器,arm保持了强大的向后兼容性,也背上了沉重的历史。ARMv9-A为了达到更高的性能,新架构甩掉历史包袱,取消了对aarch32的支持。但arm32指令集应用至今,2022年11月,联发科发布了天矶9200芯片,包含一个Cortex-X3超大核心,两个Cortex-A715大核、两个Cortex-A710中核和三个Cortex-A510小核。与树莓派一样,这颗A510小核仍然保留对arm32的支持。
3. GNU工具
首先需要工具
GNU 工具链toolchain,是底层开发必不可少的工具。如果开发机不是arm native架构,我们需要安装交叉编译cross-compiling的版本。
https://developer.arm.com/downloads/-/gnu-rm
arm-none-eabi 分别代表了ARCH-VENDOR-OS-LIBC(vendor省略了)
汇编的本质就是32bit二进制指令的助记符,一行一行的汇编指令对应的恰好是一个一个计算机能理解的32bit数字,我们需要用GNU Binutils的两个工具帮助从汇编生成二进制文件
可参考Documentation for binutils 2.39
-
as 汇编器 Assembler