t7sqynt3 发表于 2020-7-22 06:56

ARM汇编 0.基础知识与工具

本帖最后由 t7sqynt3 于 2020-7-22 09:39 编辑

前言:逆向工程需要汇编基础,先尝试整理目前所学的ARM汇编知识。由于水平有限,可能会有所疏漏,欢迎进行指正和讨论。此系列为原创,如引用需标明出处。然而,不建议作为学术研究的引用,因为内容未经过peer review。

# 0.基础知识与工具

## ARM的特点

ARM,原指Acorn RISC Machine,而RISC=reduced instruction set computer,相对于CISC(complex instruction set computer)。RISC的特点是很多指令仅需1 CPU cycle即可执行,但是同样的程序所需指令的数量通常比CISC多。而CISC则相反,减少了程序所需指令数量,但是存在复杂的指令,需要数个CPU cycles执行。

## ARM与Intel汇编的对比

- 指令集和syntax有所不同

- ARM的指令是定长的,Intel不是

- Intel是little endian,ARM支持little/big endian

- ARM没有为复杂指令保留的registers,因此有更多general purpose registers

- ARM指令执行效率优化方法与Intel有所不同

- stack frames细节有不同

## 前提

以下是此系列中用于学习的前提,不代表学习ARM汇编必须使用以下配置。

1. 已有知识:C语言基础,最好有一些汇编基础(可以是非ARM汇编)和VIM编辑器基础。

2. 环境:Cortex-A series CPU (armv7+) + Raspbian (RPI的OS) 或 Debian 或其他常用Linux分支 + GCC (target: arm-linux-gnueabi / arm-linux-gnueabihf)

3. Endianness: Little Endian

4. Word size: 4 bytes (32 bits)

5. Assembly Syntax: GNU

## 工具

1. (可选) QEMU,如果没有ARM CPU,则推荐使用(或同类模拟工具)。否则,需要GCC Arm toolchain,配置较为麻烦,而且调试仍然需要ARM CPU / simulation。如果使用Debian,可以直接用通用UEFI启动;如果使用Raspbian,注意需要使用修改过的内核启动。修改的Linux内核可以在网上搜索获取或自行patch+编译,注意versatilepb和vexpress所需内核不同,并且不同版本的Raspbian可能需要不同版本的修改内核启动。

2. (建议) ARM Keil MDK / DS-5 / Development Studio,可以用于学习指令效率。其中DS-5 / Development Studio功能比较齐全(DS-5已停止维护),可以模拟Cortex-A series CPU,但是获取途径和授权比较复杂,对于自学来说不推荐。MDK只支持模拟Microcontroller,typically Cortex-M series CPU,模拟设备的内存和ROM都比较小,并且MDK免费版(MDK-Lite)最大只支持32KB code and data,但是学习用途足够。本人选用的是MDK。

3. (建议) VIM,在Raspbian或其他Linux OS中。可以使用Emacs等其他编辑器。

## 工具配置

1. QEMU for windows
   
   在cmd中运行的命令(可存为script):
   
   ```
   ".\qemu-system-arm.exe" ^
   -kernel zImage ^
   -m 512 ^
   -M vexpress-a9 ^
   -serial stdio ^
   -append "root=/dev/mmcblk0p2" ^
   -sd 2017-07-05-raspbian-jessie-lite.img ^
   -dtb vexpress-v2p-ca9.dtb ^
   -net nic ^
   -net user,hostfwd=tcp::2222-:22 ^
   -no-reboot
   ```
   
   其中,`zImage`为修改的linux内核启动,`2017-07-05-raspbian-jessie-lite.img`为系统镜像,`vexpress-v2p-ca9.dtb`是Device Tree Blob(包含模拟硬件信息,需要与修改的内核匹配)。如果有不能启动的情况,注意错误信息。有些时候会有blocks检测有问题的时候,注意img的大小是否与内核expected block size对齐,img分区有问题(包括移除不必要的gap)可以使用任意分区修改工具。
   
   其他操作系统的QEMU配置类似,注意命令语法不同。

2. Keil MDK
   
   可以选用DFP来更全面地模拟设备(需要注意授权,有些并非免费/自由使用),但是仅学习ARM汇编可以直接使用内置software pack。
   
   一般学习调试时使用设备ARMCM3(Cortex-M3),software pack使用ARM CMSIS,包含完整的模拟(No FVP for MDK-Lite)。创建Project后,先打开Options for target,在Debug tab中,选择Use simulator(如果你有MDK-Pro license,也可以在右边选用Models Cortex-M Debugger,可以使用FVP以进行更好的模拟;与simulator的区别可见ARM Keil网站)。CPU DLL和Dialog DLL应该都会在创建Project选择设备后自动填充,如果没有的话,很有可能是该设备/DFP不支持simulator。ARMCM3默认值应该是CPU DLL: SARMCM3.DLL (-MPU), Dialog DLL: DCM.DLL (-pCM3)。在Manage Run-Time Environment中,CMSIS-Core勾选,Device-Startup勾选,即可正常编译和调试程序。如果需要程序redirect stdin/stdout/stderr to serial-debug (printf) window,则需要在Options for target的Target tab中选择Use MicroLIB,在Manage Run-Time Environment中勾选Compiler-I/O-STDERR/STDIN/STDOUT,并在variant选择ITM。
   
   默认配置下,assembler是armclang/armasm而不是GCC,由于是assembler,对于研究指令效率没有什么差别。一定要使用GCC的话,配置会更复杂一些,需要使用GCC Arm toolchain(arm官方有提供),而且不直接支持redirect stdin/stdout/stderr,需要自己写代码进行redirect。并且默认的startup code可能也需要更改,虽然会提供ld script在Run-Time Environment的Device里。

3. VIM
   
   可以使用自己习惯的.vimrc,一般来说,包括基本的syntax on,set autoindent,set smartindent即可。

## 汇编代码规范

- tabstop=8,VIM默认设置,Keil MDK中可以在Edit-Configuration-Editor中设置。

- Tab indent, no spaces (VIM关闭expandtab,set noexpandtab;Keil MDK在Edit-Configuration-Editor中不勾选Insert spaces for tabs)

- Indent code into 4 columns:

label: operation operand(s) @comment

- A whole line of comment:

@ a line of comment (without indentation)

- 没有一行过长的代码(typically <= 80 chars / line)

- Appropriate file and function headers, and other comments

moranyuyan 发表于 2020-7-22 09:39

谢谢分享

tzhv_9w6 发表于 2020-8-14 11:41

想学习下ARM汇编,谢谢楼主

wsf5201314 发表于 2021-2-27 14:33

谢谢分享{:1_921:}
页: [1]
查看完整版本: ARM汇编 0.基础知识与工具