👹
Carlos's Tech Blog
  • 🧔ECUs
    • ZYNQ_Documents
      • [ZYNQ] 构建ZYNQ的BSP工程
      • [ZYNQ] 启动流程
      • [ZYNQ] Secure Boot Flow
      • [ZYNQ] Provisioning Guideline
      • [ZYNQ] Decrypting Partition by the Decrypt Agent Using PUF key
      • [ZYNQ] enabling the cryptsetup on ramdisk
      • [ZYNQ] Encrypt external files based on file system using PUF key
      • [ZYNQ] Loading an Encrypted Linux kernel at U-Boot with a KUP Key
      • [ZYNQ] cross-compile the cryptsetup on Xilinx ZYNQ aarch64 platform
      • [ZYNQ] Linux Linaro系统镜像制作SD卡启动
    • S32G_Documents
      • [S32G] Going through the s32g hard/soft platform
      • [S32G] S32g247's Secure Boot using HSE firmware
        • S32g2 HSE key config
        • How S32g verify secure boot image
        • S32g secure boot signature generation
        • How to download and build S32g Secure boot image
        • [S32G] OTA with Secure Boot
    • RT117x_Documents
      • [RT-117x]IMX RT1170 Provisioning Guideline
      • [RT-117x] Going through the MX-RT1170 hard/soft platform
      • [RT-117x] i.MX-RT1170's Secure Boot
        • [RT-117x]Signing image with the HSM (SignServer)
    • LS104x_Documents
      • [LS104x] bsp project
      • [LS104x] boot flow
      • [LS104x] secure boot
      • [LS104x] Application Note, Using the PKCS#11 in TCU platform
      • [LS104x] 使用ostree更新rootfs
      • [LS104x] ostree的移植
      • [LS104x] Starting with Yocto
      • [LS104x] 使用FIT的kernel格式和initramfs
    • IMX6/8_Documents
      • [IMX6] Defining A U-Boot Command
      • NXP IMX6 嵌入式板子一些笔记
      • NXP-imx6 initialization
    • Vehicle_Apps
      • [SecOC] Tree
        • [SecOC] SecOC Freshness and MAC Truncation
  • 😾TECH
    • Rust Arm OS
      • ARMv7m_Using_The_RUST_Cross_Compiler
    • ARM
      • ARM-v7-M
        • 01_ARMv7-M_处理器架构技术综述
        • 02_ARMv7-M_编程模型与模式
        • 03_ARMv7-M_存储系统结构
        • 04_ARMv7-M_异常处理及中断处理
      • ARM-v8-A
        • 02_ARMv8_基本概念
        • 03_ARMv8_指令集介绍_加载指令集和存储指令集
        • 04_ARMv8_指令集_运算指令集
        • 05_ARMv8_指令集_跳转_比较与返回指令
        • 06_ARMv8_指令集_一些重要的指令
        • 0X_ARMv8_指令集_基于汇编的UART驱动
        • 07_ARMv8_汇编器Using as
        • 08_ARMv8_链接器和链接脚本
        • 09_ARMv8_内嵌汇编(内联汇编)Inline assembly
        • 10_ARMv8_异常处理(一) - 入口与返回、栈选择、异常向量表
        • 11_ARMv8_异常处理(二)- Legacy 中断处理
        • 12_ARMv8_异常处理(三)- GICv1/v2中断处理
        • 13_ARMv8_内存管理(一)-内存管理要素
        • 14_ARMv8_内存管理(二)-ARM的MMU设计
        • 15_ARMv8_内存管理(三)-MMU恒等映射及Linux实现
        • 16_ARMv8_高速缓存(一)cache要素
        • 17_ARMv8_高速缓存(二)ARM cache设计
        • 18_ARMv8_高速缓存(三)多核与一致性要素
        • 19_ARMv8_TLB管理(Translation Lookaside buffer)
        • 20_ARMv8_barrier(一)流水线和一致性模型
        • 21_ARMv8_barrier(二)内存屏障案例
      • ARM Boot Flow
        • 01_Embedded_ARMv7/v8 non-secure Boot Flow
        • 02_Embedded_ARMv8 ATF Secure Boot Flow (BL1/BL2/BL31)
        • 03_Embedded_ARMv8 BL33 Uboot Booting Flow
      • ARM Compiler
        • Compiler optimization and the volatile keyword
      • ARM Development
        • 在MACBOOK上搭建ARMv8架构的ARM开发环境
        • Starting with JLink debugger or QEMU
    • Linux
      • Kernel
        • 0x01_LinuxKernel_内核的启动(一)之启动前准备
        • 0x02_LinuxKernel_内核的启动(二)SMP多核处理器启动过程分析
        • 0x21_LinuxKernel_内核活动(一)之系统调用
        • 0x22_LinuxKernel_内核活动(二)中断体系结构(中断上文)
        • 0x23_LinuxKernel_内核活动(三)中断体系结构(中断下文)
        • 0x24_LinuxKernel_进程(一)进程的管理(生命周期、进程表示)
        • 0x25_LinuxKernel_进程(二)进程的调度器的实现
        • 0x26_LinuxKernel_设备驱动(一)综述与文件系统关联
        • 0x27_LinuxKernel_设备驱动(二)字符设备操作
        • 0x28_LinuxKernel_设备驱动(三)块设备操作
        • 0x29_LinuxKernel_设备驱动(四)资源与总线系统
        • 0x30_LinuxKernel_设备驱动(五)模块
        • 0x31_LinuxKernel_内存管理(一)物理页面、伙伴系统和slab分配器
        • 0x32_LinuxKernel_内存管理(二)虚拟内存管理、缺页与调试工具
        • 0x33_LinuxKernel_同步管理_原子操作_内存屏障_锁机制等
        • 01_LinuxDebug_调试理论和基础综述
      • Userspace
        • Linux-用户空间-多线程与同步
        • Linux进程之间的通信-管道(上)
        • Linux进程之间的通信-管道(下)
        • Linux进程之间的通信-信号量(System V)
        • Linux进程之间的通信-内存共享(System V)
        • Linux进程之间的通信-消息队列(System V)
        • Linux应用调试(一)方法、技巧和工具 - 综述
        • Linux应用调试(二)工具之coredump
        • Linux应用调试(三)工具之Valgrind
        • Linux机制之内存池
        • Linux机制之对象管理和引用计数(kobject/ktype/kset)
        • Linux机制copy_{to, from}_user
        • Linux设备树 - DTS语法、节点、设备树解析等
        • Linux System : Managing Linux Services - inittab & init.d
        • Linux System : Managing Linux Services - initramfs
      • Kernel Examples
        • Linux Driver - GPIO键盘驱动开发记录_OMAPL138
        • 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl
        • 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(二)之cdev与read、write
        • 基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ
        • Linux内核调用SPI驱动_实现OLED显示功能
        • Linux内核调用I2C驱动_驱动嵌套驱动方法MPU6050
    • OPTEE
      • 01_OPTEE-OS_基础之(一)功能综述、简要介绍
      • 02_OPTEE-OS_基础之(二)TrustZone和ATF功能综述、简要介绍
      • 03_OPTEE-OS_系统集成之(一)编译、实例、在QEMU上执行
      • 05_OPTEE-OS_系统集成之(三)ATF启动过程
      • 06_OPTEE-OS_系统集成之(四)OPTEE镜像启动过程
      • 07_OPTEE-OS_系统集成之(五)REE侧上层软件
      • 08_OPTEE-OS_系统集成之(六)TEE的驱动
      • 09_OPTEE-OS_内核之(一)ARM核安全态和非安全态的切换
      • 10_OPTEE-OS_内核之(二)对安全监控模式的调用的处理
      • 11_OPTEE-OS_内核之(三)中断与异常的处理
      • 12_OPTEE-OS_内核之(四)对TA请求的处理
      • 13_OPTEE-OS_内核之(五)内存和cache管理
      • 14_OPTEE-OS_内核之(六)线程管理与并发
      • 15_OPTEE-OS_内核之(七)系统调用及IPC机制
      • 16_OPTEE-OS_应用之(一)TA镜像的签名和加载
      • 17_OPTEE-OS_应用之(二)密码学算法和安全存储
      • 18_OPTEE-OS_应用之(三)可信应用的开发
      • 19_OPTEE-OS_应用之(四)安全驱动开发
      • 20_OPTEE-OS_应用之(五)终端密钥在线下发系统
    • Binary
      • 01_ELF文件_目标文件格式
      • 02_ELF文件结构_浅析内部文件结构
      • 03_ELF文件_静态链接
      • 04_ELF文件_加载进程虚拟地址空间
      • 05_ELF文件_动态链接
      • 06_Linux的动态共享库
      • 07_ELF文件_堆和栈调用惯例以ARMv8为例
      • 08_ELF文件_运行库(入口、库、多线程)
      • 09_ELF文件_基于ARMv7的Linux系统调用原理
      • 10_ELF文件_ARM的镜像文件(.bin/.hex/.s19)
    • Build
      • 01_Script_makefile_summary
    • Rust
      • 02_SYS_RUST_文件IO
    • Security
      • Crypto
        • 1.0_Security_计算机安全概述及安全需求
        • 2.0_Security_随机数(伪随机数)
        • 3.0_Security_对称密钥算法加解密
        • 3.1_Security_对称密钥算法之AES
        • 3.2_Security_对称密钥算法之MAC(CMAC/HMAC)
        • 3.3_Security_对称密钥算法之AEAD
        • 8.0_Security_pkcs7(CMS)_embedded
        • 9.0_Security_pkcs11(HSM)_embedded
      • Tools
        • Openssl EVP to implement RSA and SM2 en/dec sign/verify
        • 基于Mac Silicon M1 的OpenSSL 编译
        • How to compile mbedtls library on Linux/Mac/Windows
    • Embedded
      • eMMC启动介质
  • 😃Design
    • Secure Boot
      • JY Secure Boot Desgin
    • FOTA
      • [FOTA] Module of ECUs' FOTA unit design
        • [FOTA] Tech key point: OSTree Deployment
        • [FOTA] Tech key point: repositories role for onboard
        • [FOTA] Tech key point: metadata management
        • [FOTA] Tech key point: ECU verifying and Decrpting
        • [FOTA] Tech key point: time server
      • [FOTA] Local-OTA for Embedded Linux System
    • Provisioning
      • [X-Shield] Module of the Embedded Boards initialization
    • Report
由 GitBook 提供支持
在本页
  • 07_ARMv8_汇编器Using as
  • 1 关键字
  • 2 汇编宏
  • Ref
  1. TECH
  2. ARM
  3. ARM-v8-A

07_ARMv8_汇编器Using as

https://github.com/carloscn/blog/issues/19

07_ARMv8_汇编器Using as

  • 关键字

  • 伪指令

  • 汇编宏

1 关键字

1.1 label 和 symbol

代表它所在的地址,也可以当做变量或者符号。

  • 全局symbol:.global xxxxx

  • 局部symbol (label):在函数内使用,开头以0-99直接的数字为标号名,通常和b指令结合使用。

  • f:指示编译器向前搜索

  • b:指示编译器向后搜索

.global my_sym

my_sym:
		mov x1, 0x80000
		mov x2, 0x200000
		add x3, x1, 32
1:
		ldr x4, [x1], #8
		str x4, [x2], #8
		cmp x1, x3
		b.cc 1b								# 向1 symbol后面的代码执行。
		
		ret

1.2 伪指令

对齐伪指令.align

声明align后面的汇编必须从下一个能被2^n整除的地址开始分配。ARM64系统中,第一个参数表示2^n大小。

Define: .align [abs-expr[, abs-expr[, abs-expr]]

.align 3						# 2^3 = 8 字节对齐
.global string1
string1:
		.string "Boot at EL"

string1的地址必须是能被8整除的。

数据定义伪指令

  • .byte 把8位数当做数据插入到汇编当中

  • .hword 把16位数当成数据插入到汇编当中

  • .long和.int:把32位数当成数据插入到汇编当中

  • .quad:64位数

  • .float:浮点数

  • .ascii "string":把string当做数据插入到汇编当中,ascii未操作定义字符串需要自行插入‘\0’

  • .asciz "string": 不需要手动插入'\0'的string。

执行伪指令

  • .rept:重复执行伪指令

  • .equ和.set:赋值操作 .equ symbol, expression

.rept 3
.long 0
.endr
# 等效于
.long 0
.long 0
.long 0
# 赋值例子
.equ data01, 100
.equ data02, 50

.global main
main:
	ldr x2, =data01
	ldr x3, =data02

函数相关伪指令

  • .gloabl:定义一个全局的符号,可以为变量可以为函数

  • .include:引用头文件

  • .if, .else, .endif:控制语句

  • .ifdef symbol:判断symbol是否定义

  • .ifndef symbol:未定义

  • .ifc string1, string2:判断两个字符串是否相等

  • .ifeq expression: 判断expression的值是否为0

  • .ifeqs string1, string2: 等同于ifc

  • .ifge expression:判断值是否≥0

  • .ifle expression:判断值是否≤0

  • .ifne expression:判断值是否不为0

运算符
说明

expr1 == expr2

若 expr1 等于 expr2,则返回“真”

expr1 != expr2

若 expr1 不等于 expr2,则返回“真”

expr1 > expr2

若 expr1 大于 expr2,则返回"真”

expr1 ≥ expr2

若 expr1 大于等于 expr2,则返回“真”

expr1 < expr2

若 expr1 小于 expr2,则返回“真”

expr1 ≤ expr2

若 expr1 小于等于 expr2,则返回“真”

!expr1

若 expr 为假,则返回“真”

expr1expr2

对 expr1 和 expr2 执行逻辑 AND 运算

expr1 || expr2

对 1xprl 和 expr2 执行逻辑 OR 运算

expr1 & expr2

对 expr1 和 expr2 执行按位 AND 运算

CARR1?

若进位标志位置 11则返回“真”

OVERFLOW ?

若溢出标志位置 1,则返回“真”

PARITY ?

若奇偶标志位置 1,则返回“真”

SIGN ?

若符号标志位置 1,则返回“真”

ZERO ?

若零标志位置 1,则返回“真”

段相关的伪指令

.section

.section name, "flag"

flag就是ELF文件中的adewxMSGT?可以查看文档,我们在02_ELF文件结构_浅析内部文件结构中描述了ELF的段的结构,可以参考。

  • b

    bss section (uninitialized data)

  • n

    section is not loaded

  • w

    writable section

  • d

    data section

  • r

    read-only section

  • x

    executable section

If no flags are specified, the default flags depend upon the section name. If the section name is not recognized, the default will be for the section to be loaded and writable.

For ELF targets, the .section directive is used like this:

.section name[, "flags"[, @type]]

The optional flags argument is a quoted string which may contain any combintion of the following characters:

  • a

    section is allocatable

  • w

    section is writable

  • x

    section is executable

例子:把符号映射到.idmap.text段,属性为awx

.section ".idmap.text", "awx"
#-----------------------------------
.section .data
.algin 3
.global my_data0
.my_data0:
		.dword 0x00
#----------------------------------- mapping to .data section
.section .text
......
#----------------------------------- mapping to .text section

.pushsection

.pushsection:下面的代码push接到指定的section当中。

.popsection

.popsection:结束push

两个伪指令需要成对使用,仅仅是把pushsection和popsection的圈出来的代码复制链接到指定的section中,其他代码还在原来的section。

.section .text
.global my_add_func
my_add_func:
	...
	ret
	
.pushsection ".idmap.text", "awx"
.global my_sub_func
my_sub_func:
	.....
	ret
.popsection

....

这个例子就是把my_sub_func从 .text段里面提取出来然后链接到.idmap.text里面。

实验

【题目】

使用汇编的数据定义伪指令,可以实现表的定义,例如Linux内核使用.quad和.asciz定义了一个kallsyms的表,地址和函数名的对应关系:

  • 0x800800 -> func_a

  • 0x800860-> func_b

  • 0x800880-> func_c

请在汇编里定义一个类似的表,在C语言中根据函数的地址查找表,并且正确打印函数的名称。这个非常常用,我们在调试死机状态的时候可以根据这样的方法把函数的调用名称和栈指针打出来,方便我们调试。

.align 3
.global func_addr
func_addr:
	.qual 0x800800
	.qual 0x800860
	.qual 0x800880

.align 3
.global func_str
func_str:
	.asciz "func_a"
	.asciz "func_b"
	.asciz "func_c"

.align 3
.global func_num_syms
func_num_syms:
	.quad 3
extern unsigned long func_addr[];
extern char func_str[];
extern unsigned long func_num;
extern int add_f(int a, int b, int c);

static int print_func_name(unsigned long addr)
{
	int i = 0;
	char *p, *str;

	for (i = 0; i < func_num; i++) {
		if (addr == func_addr[i]) {
			goto found;
		}
	}
	uart_send_string("not found func\n");

found:
	p = (char *)&func_str;
	while(1) {
		p++;
		if (*p == '\0') {
			i--;
		}
		if (i == 0) {
			p++;
			str = p;
			uart_send_string(str);
			break;
		}
	}
	return 0;
}

2 汇编宏

2.1 定义

.macro macname macargs ...

.endm

示例1:

.macro add p1 p2
add x0, \p1, \p2
.endm

#可以配置初始值
.macro reserve_str p1=0, p2

#特殊字符(错误使用)
.macro opcode base length
\base.\length
.endm

.macro opcode base length
\base\().\length
.endm

在kernel里面有这样的代码:

.macro kernel_ventry, el, label, regsize = 64
.algin 7
sub sp, sp, #S_FRAME_SIZE
b el\()\el()_\label
.endm

最后结果是b el1_irq

2.2 实验

在汇编文件通过如下两个函数:

  • long add_1(a, b)

  • long add_2(a, b)

然后写一个宏定义

.macro add a, b, label

#这里调用add_1或者add_2函数,label等于1或者2

.endm

.align 3
add_1:
	add x0, x0, #1
	add x0, x0, x1
	ret

.align 3
add_2:
	add x0, x0, #2
	add x0, x0, x1
	ret

.global add_func
.macro add_func a, b, label
.align 3
	mov x0, \a
	mov x1, \b
	bl add_\()\label
.endm


macro1:
	mov x9, x30
	add_func x0, x1, 1
	mov x30, x9
	ret

macro2:
	mov x9, x30
	add_func x0, x1, 2
	mov x30, x9
	ret

.global add_f
.align 3
add_f:
	mov x9, x30
	cmp x2, 1
	b.eq macro1

	cmp x2, 2
	b.eq macro2

	mov x30, x9
	ret

Ref

上一页0X_ARMv8_指令集_基于汇编的UART驱动下一页08_ARMv8_链接器和链接脚本

最后更新于1年前

If the optional argument to the .section directive is not quoted, it is taken as a subsegment number (see section ).

😾
Sub-Sections
Using as - GNU Assembler, [.section name]