👹
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 提供支持
在本页
  • 04_ARMv8指令集-运算指令集
  • 1. 加法指令
  • 2. 减法指令
  • 3. 位操作
  • Ref
  1. TECH
  2. ARM
  3. ARM-v8-A

04_ARMv8_指令集_运算指令集

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

04_ARMv8指令集-运算指令集

  • 加法指令ADD、ADDS、ADCS

  • 减法指令SUB、SUBS、SBC,SBCS,CMP

  • 位操作AND, ANDS, ORR、EOR、BFI、UBFX、SBFX

1. 加法指令

加法指令有ADD、ADDS、ADCS。 ADD一般性加法指令,ADCS带C标志位运算的加法指令,ADDS影响C标志位的加法运算。

1.1 ADD

a = a + b, 没有进位标志,也不会利用进位标志

  • ADD (extended register) :

    • Define: ADD <Xd|SP>, <Xn|SP>, <Wm>, {<extend> {#<amount>}}

    • Example1: add x0, x1, x2 ( x0 = x1 + x2 )

    • Example2: add x0, x1, x2, lsl #5( x0 = x1 + (x2 << 5) )

  • ADD (immediate):

    • Define: ADD <Xd|SP>, <Xn|SP>, #<imm>{, lsl <#shift>}, note shift supports #0 and #12 only.

    • Example1: add x1, x2, #8 (x1 = x2 + 8)

    • Example2: add x1, x2, #8, lsl #12 ( x1 = x2 + (8 << 12) )

  • ADD (shifted register):

    • Define: ADD <Xd>, <Xn>, <Xm>{, <shift> #<amount>} , note #amount range 0 to 63

    • Note: LSL when shift = 0, LSR when shift = 1, ASR when shift = 2

    • Example1: add x1, x2, x3, asr #2

1.2 ADDS

(a,C) = a + b, 带进位标志的加法,用法和ADD一样

1.3 ADCS

(a,C) = a + b + C,带进位标志的加法,且需要加上C标志位,用法和ADD一样。 注意,如果加法溢出的时候C标志位会置位为1,比如,a = 0xFFFFFFFFFFFFFFFF, b = 1,此时,加法溢出,C置位1。

1.4 ADR

a = b + PC, 当前程序的PC值加上给定的地址偏移

  • ADR

    • Define: ADR <Xd>, <label>

    • Note, no 32-bit

    • Note, range ±1MB, offset from the address of this instruction.

    • Example01: adr x1, #25

1.5 关于查看C flag的方法

方法1:使用MSR/MRS指令

	msr NZCV, xzr	   // clear the NZCV
	mrs x0, NZCV     // 查看NZCV寄存器,NZCV在高位28 - 32 bits

方法2:使用ADCS的+C特性

adcs x0, zxr, xzr 让两个0寄存器相加 0+0+c就可以得到C标志位的值

2. 减法指令

减法指令包含SBC,SBCS。请参考ARMv8手册,C6.2.231 C6-1299

2.1 SUB

a = a - b, 没有进位标志,也不会利用进位标志。使用方法和ADD一致。

2.2 SUBS

(a,N) = a - b, 会置标志位N。使用方法和SUBS一致,减成负数的时候,其余位置补1。

2.3 SBC

a = a - b - 1 + C

  • SBC (Subtract with Carry):

    • Define: SBC <Xd>, <Xn>, <Xm>

    • Example: sbc x0, xzr, xzr

2.4 SBCS

(a, N) = a - b - 1 + C, 如果减出负数的话,N会被置位

  • SBC (Subtract with Carry, setting N flag):

    • Define: SBCS <Xd>, <Xn>, <Xm>

    • Example: sbcs x0, xzr, x1

2.5 CMP

比较指令,实际上也使用SBC实现的, cmp x1, x2

  • 若x1 > x2, NCZV = 0100

  • 若x1 = x2, NCZV = 0110

  • 若x1 < x2, NCZV = 1000

Define 1: CMP <Xn|SP>, <R><m>{, <extend> {#<amount>}}

Define 2: CMP <Xn|SP>, #<imm>{, <shift>}

Define 3: CMP <Xn|SP>, <Xm>{, <shift> #<amount>}

Example:

** The function cmp_and_return_test:*

** if a >= b return 1*

** if a < b return 0*

test_cmp:
	cmp x0, x1   			// if x0 >= x1,  C is 1; if x0 < x1 C is 0
  adcs x0, xzr, xzr // 0 + 0 + C

3. 位操作

位操作包含AND, ANDS, ORR、EOR、BFI、UBFX、SBFX, 分别是与、与置位标志位、或、异或、插入、无符号提取、有符号提取。

3.1 ORR

a = a | b;

Define 1: ORR <Xd|SP>, <Xn>, #<imm>

Define 2: ORR <Xd|SP>, <Xn>, <Xm>{, <shift> #<amount>}

test_orr:
	// ORR test  0xAA oor 0x55 = 0xFF
	//           0xFF oor 0x00 = 0xFF
	//           0xFF oor 0xFF = 0xFF
	//           0x00 oor 0x00 = 0x00
	mov x0, xzr
	mov x1, #0xAA
	mov x2, #0x55
	orr x1, x1, x2

	mov x1, #0xFF
	orr x1, x1, xzr

	mov x1, #0xFF
	orr x1, x1, x1

	orr x1, xzr, xzr

	ret



test_ubfx:
	// x1: 0000 0000 0000 0000  ->  0000 0000 0000 1111
	//                     ^
	//                     |
	// x2:      0000 0000 1111 0000
	mov x1, xzr
	mov x2, #0x00F0
	ubfx x1, x2, #0x4, #0x4

	// x1: 0000 0000 0000 0000  ->  1111 1111 1111 1111
	//                     ^
	//                     |
	//          1000 0000 1111 0000
	mov x1, xzr
	mov x2, #0x80F0

3.2 EOR

a = a ^ b;

Define 1: EOR <Xd|SP>, <Xn>, #<imm>

Define 2: EOR <Xd|SP>, <Xn>, <Xm>{, <shift> #<amount>}

test_eor:
	// test 2 exchange the value x1 = 0x07, x2 = 0xAA
    // using the orr, just use two register.
	// x1 = x1^x2
	// x2 = x2^x1
	// x1 = x1^x2
	ldr x1, =0x07
	ldr x2, =0xAA
	eor x1, x1, x2
	eor x2, x2, x1
	eor x1, x1, x2
	ret

几个EOR的小技巧:

  • 翻转某些位: 比如把右数第0位到第3位翻转: 1010 1001 ^ 0000 1111 = 1010 0110

  • 交换数值: a=a^b; b=b^a; a=a^b,不借助第三个变量

  • 置0: a^a

  • 判断相等 a^b == 0

3.3 AND

3.3.1 AND

a = a & b;

Define 1: AND <Xd|SP>, <Xn>, #<imm>

Define 2: AND <Xd|SP>, <Xn>, <Xm>{, <shift> #<amount>}

	msr NZCV, xzr	   // clear the NZCV
	ldr x1, =0xAA
	ldr x2, =0x0
	// test AND, no Z flag. x1 = x1&x2
	and x1, x1, x2
	mrs x0, NZCV

3.3.2 ANDS

(a, z) = a & b. 如果a和b与的结果为0,z flag置位

	// test ANDS, z flag, if the result is 0, Z is 1
	msr NZCV, xzr	   // clear the NZCV
	mov x0, xzr
	ldr x1, =0xAA
	ands x1, x1, x2
	mrs x0, NZCV

3.4 BFI

Define 1: BFI <Xd>, <Xn>, #<lsb>, #<width>

从Xn寄存器里面从低位开始,插入到Xd寄存器从#开始,#长度。

读取Xn寄存器的低位开始计算,插入到Xd寄存器从#开始,#长度。这个没有办法控制Xd的位置,只能从Xd的最低位开始。

test_bfi:
	// 0000 0000 0000 1010
	//                 |
	//                 V
	//           0000 0000 0000 0000  ->  0000 1010 0000 0000
	ldr x1, =0x000A
	mov x2, xzr
	bfi x2, x1, #0x8, #0x4

	// 0000 0000 0000 1010
	//                 |
	//                 V
	//           0000 0101 0000 0000  ->  0000 1010 0000 0000
	ldr x1, =0x000A
	mov x2, #0x0500
	bfi x2, x1, #0x8, #0x4

	ret

3.5 UBFX/SBFX

Define: UBFX <Xd>, <Xn>, #<lsb>, #<width>

Define: SBFX <Xd>, <Xn>, #<lsb>, #<width>

读取Xn寄存器的#开始,#长度开始计算,替换到Xd寄存器低位的位置#长度。这个没有办法控制Xd的位置,只能从Xd的最低位开始。 SBFX是有符号的,替换之后Xd 其他位0变为1。

	// x1:      0000 0000 1111 0000
	//                     |
	//                     V
	// x2: 0000 0000 0000 0000  ->  0000 0000 0000 1111

	mov x1, #0x00F0
	mov x2, xzr
	ubfx x2, x1, #0x4, #0x4

	//          1000 0000 1111 0000
	//                     |
	//                     V
	// x1: 0000 0000 0000 0000  ->  1111 1111 1111 1111
	mov x1, #0x80F0
	mov x2, xzr
	sbfx x2, x1, #0x4, #0x4

Ref

[1] Arm Armv8-A Architecture Registers-NZCV, Condition Flags

[2] ARM Cortex-A Series Programmer's Guide for ARMv8-A - Arithmetic and logical operations

[3] ARM架构(三)ARMv8 Programm Model Overview

[4] ARMv8官方手册学习笔记(三):寄存器

上一页03_ARMv8_指令集介绍_加载指令集和存储指令集下一页05_ARMv8_指令集_跳转_比较与返回指令

最后更新于1年前

😾