Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

04_ARMv8_指令集_运算指令集 #3

Open
carloscn opened this issue Mar 19, 2022 · 0 comments
Open

04_ARMv8_指令集_运算指令集 #3

carloscn opened this issue Mar 19, 2022 · 0 comments
Labels

Comments

@carloscn
Copy link
Owner

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 06_ARMv8_指令集_一些重要的指令 #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

image-20220319154625842

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官方手册学习笔记(三):寄存器

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant