20230814 chapter2

发布时间 2023-08-17 00:24:49作者: 杨大茄子

 负数的表示方法,补码

比如一个正数 1的补码就是 加上就溢出等于0的值,

byte范围内,256就溢出了,所以1的补码就是256-1=255,0xFF,所以-1就是FF

另一种计算方法是,负数等于正数的反码加一;

1补数就是反码!

 大小端:arm同时支持大小端,但一般都采用小端,

carry flag 就是2大数相加溢出;

逻辑左移或右移,简单粗暴的按位移动,移出的最后一位进入carry flag

算术右移,正数左边补0,负数左边补1.

伪指令:为了尽可能减少指令种类,伪指令能增加可读性,使用objdump时 添加参数 -M no-aliases 可以看到真实底层指令

MOV X0, X1 actually translates to ORR X0, XZR, X1

 

mov 的立即数 只能是16bit,移位只能是0,16,32,48;

movk,move keep :把数移到某16位,其他位不变

MOV X2, #0x6E3A  //其他位为0,其底层是一个movz
MOVK X2, #0x4F5D, LSL #16  //把数移到x2的第二个16bits,其他bits不变
MOVK X2, #0xFEDC, LSL #32
MOVK X2, #0x1234, LSL #48
 

操作数2的三种形式!

1,寄存器 和一个移动

MOV X1, X2, LSL #1 // Logical shift left

MOV X1, X2, LSR #1 // Logical shift right
MOV X1, X2, ASR #1 // Arithmetic shift right
MOV X1, X2, ROR #1 // Rotate right

 上面的可以写成下面的伪指令

LSL X1, X2, #1 // Logical shift left
LSR X1, X2, #1 // Logical shift right
ASR X1, X2, #1 // Arithmetic shift right
ROR X1, X2, #1 // Rotate right 

2,寄存器和一个扩展 

3,一个小立即数和位移

 movn move not,就是反码,0的反码是-1,  1的反码是-2, 2的反码是-3 ,正数的补码等于其反码加一,那么正数的反码就是正数的补码(就是相反数)减一;

用movn和add两条指令完成求相反数!取反加一

 Remember that the negative of a number is the

two’s complement of the number, or the one’s
complement plus one。

乘 -1 ,也就是取相反数,不要用 mul 指令,因为乘法指令比较慢,可以用取反加一两条指令,2个时钟周期完成;

move.s

//
// Examples of the MOV instruction.
//
.global _start // Provide program starting address
// Load X2 with 0x1234FEDC4F5D6E3A first using MOV and MOVK
_start: MOV X2, #0x6E3A
 MOVK X2, #0x4F5D, LSL #16
 MOVK X2, #0xFEDC, LSL #32
 MOVK X2, #0x1234, LSL #48
// Just move W2 into W1
 MOV W1, W2
// Now lets see all the shift versions of MOV
 MOV X1, X2, LSL #1 // Logical shift left
 MOV X1, X2, LSR #1 // Logical shift right
 MOV X1, X2, ASR #1 // Arithmetic shift right
 MOV X1, X2, ROR #1 // Rotate right
// Repeat the above shifts using mnemonics.
 LSL X1, X2, #1 // Logical shift left
 LSR X1, X2, #1 // Logical shift right
 ASR X1, X2, #1 //Arithmetic shift right
 ROR X1, X2, #1 // Rotate right
// Example that works with 8 bit immediate and shift
 MOV X1, #0xAB000000 // Too big for #imm16
// Example of MOVN
 MOVN W1, #45
// Example of a MOV that the Assembler will change to MOVN
 MOV W1, #0xFFFFFFFE // (-2)
// Setup the parameters to exit the program
// and then call Linux to do it.
 MOV X0, #0 // Use 0 return code
 MOV X8, #93 // Serv command code 93 terms
 SVC 0 // Call linux to terminate

  Makefile:

TARGET=move
$(TARGET): $(TARGET).o
	ld -o $@  $^

%.o:%.s
	as -o $@ $<

  A=a  类似声明变量,$(A) 取变量A的内容;

目标:依赖

  命令内容

冒号前面是目标【类似汇编的label】,冒号后面的是依赖,可以是多个依赖,$@ 取目标内容;$< 取第一个依赖;$^ 取所有依赖;

 

makefile 写法:  https://seisman.github.io/how-to-write-makefile/  

 

经测试,linux返回值好像确实只返回一个无符号byte!

指令追加s则set 32位操作码的bit29 通知设置标志位,标志好像有4种,后面学;

 .global _start

_start:
        mov  w0,0xffff0000
        add w0,w0,w0
        b.cs     ret1
        b       ret0

ret0:
        mov w0,0
        mov x8,93
        svc 0
ret1:
        mov w0,1
        mov x8,93
        svc 0

  

上面的代码返回0,把add换成adds则会设carry标志返回1,因为相加进位溢出了,b.cs  = Carry set 跳转

 adc   add with carry flag。

下面例子中adds进位了,set carry,adc命令中 x0=x2+x4+1

//
// Example of 128-Bit addition with the ADD/ADC instructions.
//
.global _start

// Load the registers with some data
// First 64-bit number is 0x0000000000000003FFFFFFFFFFFFFFFF
_start:
        mov     x2,0x0000000000000003
        mov     x3,0xffffffffffffffff   //Assem will change to MOVN
// Second 64-bit number is 0x00000000000000050000000000000001
        mov     x4,0x0000000000000005
        mov     x5,0x0000000000000001
        adds    x1,x3,x5        // Lower order 64-bits
        adc     x0,x2,x4        // Higher order 64-bits
// Setup the parameters to exit the program
// and then call Linux to do it.
// W0 is the return code and will be what we
// calculated above.
        mov     x8,93
        svc     0

 

 

SUBS will clear the carry flag if the result is negative and set it if positive; SBC then subtracts one if the carry flag is clear.

 

//
// do the exercise 7 of chapter 2,write a program that performs 128-bit subtraction
//
.global _start
_start:
        mov x2 ,0x9
        mov x3,0x1

        mov x4,3
        mov x5,2

        subs x1,x3,x5   //negative,C clear
        sbc x0,x2,x4    //x0=5 is expected

        mov x8,93
        svc 0

   

 For now,chapter2 ended;