arm_day10

复习:                                 

数据处理指令

一.分类                                                         

1. 数据 传送(MOV数据传送指令  MVN数据取反传送指令)

2. 算术运算(

ADD加法 ADC带进位的加法

SUB减法 SBC带借位的减法

RSB反向减法指令 RSC带借位的反向减法指令)

3. 位运算(AND与  ORR或 EOR异或  BIC位清除

4.比较测试(CMP比较指令,减法CMN负数比较指令,加法TST位测试指令,位相与TEQ测试相等指令,位异或)

二.指令格式                                                      

操作码{条件码}S  目标寄存器, 第一源操作数,  第二源操作数

 

1.数据传送指令无第一源操作数

2.比较测试指令无目标寄存器

3.比较测试指令不加S,结果影响NZCV

4.第一源操作数是寄存器

5.第二源操作数有:8位图立即数,寄存器,寄存器移位

  (LSL,LSR,ASR,ROR,RRX)

6.S:1.目标寄存器为PC,CPSR=SPSR

     2.目标寄存器不为PC,结果影响NZCV

7.加法,C进位,有进位,C=1,无进位,C=0

8.减法,C借位,有借位,C=0,无借位,C=1

 

1-10累加和

arm-linux-as-g -o sum.o sum.s

arm-linux-ld-e _start -o sum sum.o

qemu-arm -g1234 sum

 

arm-linux-gdbsum

 

最大公约数的求解

20=5X4

12=3X4

   = 2X4

 

R0=20

R1=12

R0==R1?  20!=12

R0=R0-R1=20-12=8

R1=R1-R0=12-8=4

R0=R0-R1=8-4=4

 

while(R0 !=R1)

{

    if(R0>= R1)

{

   R0 = R0– R1;

}

   else

{

  R1 = R1 – R0;

}

}

 

跳转指令

数据处理指令(传送,加法,减法,位运算,比较测试)

 

mov r1,#0x56

从存储器中获得,怎么办?

------------------------------------------------------------------------------------------------------------

Day10                                                             

(1)加载指令:将数据从存储器中读到寄存器

(2)存储指令:将处理完毕的数据(寄存器)存储回存储器

 

实现了寄存器与存储器之间的数据交互

 

单寄存器

多寄存器

 

单寄存器字和无符号字节的加载,存储指令

 

单寄存器的加载指令

LDR{cond}  Rd,  <地址模式>

功能:将指定地址单元<地址模式>的数据读入Rd中。

 

单寄存器的无符号字节加载指令

LDR{cond}B   Rd, <地址模式>

功能:将指定<地址模式>地址单元中的字节数据读入Rd中,

字节数据放在Rd的低8位,高24bit用0填充

<地址模式>:数据来源

Rd:目标寄存器

示例

LDR    R1,  [R2]     

R2=0x20008000

R1是0x20008000地址中的数据

 

LDR    PC,  [R0, #8]

 

LDRB   R1, [R2], #1

R2=0x20008000  0x56

R1=0x56

R2=R2+1=0x20008001

 

    LDR    R1, [PC, R3]

    LDR    R1,[R2,  R3, LSL #2]

    LDREQB   R1,[R2,  R3]

    LDR     R0, [R0, #8]!                  @×

    基址与目标寄存器不一样

 

 

单寄存器字和无符号字节存储指令

语法格式

STR{cond}         Rd,   <地址模式>

功能:将Rd寄存器的字数据存储到由<地址模式>指定的地址中

STR{<cond>}B    Rd, <地址模式>

功能:将寄存器中一个字节数据保存到<地址模式>指定的地址中

Rd:源寄存器

<地址模式>:数据需要存储到的目标地址

 

示例

STR    R1, [R2]

STR    R1, [R2], #1

STR    R1, [R2, R3]

STRB   R0,  [R1,  R2,  ASR #2] 

STREQB  R0,  [R1,  R2,  LSL #2]

STR    PC,  [R0, #8]  [PC, #8] 单元内容

STR     R0, [R0, #8]!     @×

 

 

1 .零偏移

LDR  R0, [R1] //将R1指定的地址中的数据加载到R0

R0=0xe92d4800

 

2. [<Rn>, #+/-<offset_12>] 偏移量为立即数(12bit)

    LDR  R0, [R1,#0x8]           ;R0<-[R1+0x8]

    LDR  R0, [R1, #-0x20]         ; R0<- [R1 – 0x20]

R0=0xe59f3060

 

3. [<Rn>, +/-<Rm>]  偏移量为寄存器

    LDR  R0,[R1, R2]                 ;R0<-[R1+R2]

    LDR  R0,[R1,-R2]                 ;R0<-[R1-R2]

 

4. [<Rn>, +/-<Rm>, <shift> #<shift_imm>] 偏移量为寄存器移位

    LDR  R0,[R1 ,R2,LSL #2]     ;R0<-[R1+R2*4]

 

5. [<Rn>, #+/-<offset_12>]!

    LDR  R0,[R1, #0x8]!       ;R0<-[R1+0x8]  R1=R1+8

   1.先加载数据

   2.改变基址

6. [<Rn>, +/-<Rm>]!

    LDR  R0,[R1,R2] !        ;R0<-[R1+R2]   R1=R1+R2

 

7. [<Rn>, +/-<Rm>, <shift> #<shift_imm>]!

LDR R0,[R1,R2,LSL #2] ! 

;R0<-[R1+R2*4]   R1=R1+R2*4

 

8. [<Rn>], #+/-<offset_12>

    LDR  R0, [R1], #0x20     ;R0=<-[R1]  R1=R1+0x20

    1.现将基址指定的数据加载到R0

    2.改变基址

 

9. [<Rn>],  +/-<Rm>

    LDR  R0, [R1], R2 ;R0=<-[R1]  R1=R1+R2

 

10. [<Rn>],  +/-<Rm>,<shift> #<shift_imm>

    LDR  R0, [R1], R2, LSL  #2;R0=<-[R1]  R1=R1+R2*4

 

地址模式:

10:

1.无偏移量,将指定基址的数据加载到寄存器,基址不变

 

2.将基址+偏移量指定地址的数据加载到寄存器,基址不变

1.立即数

2.寄存器

3.寄存器移位

 

3.将基址+偏移量指定地址的数据加载到寄存器,基址=基址+偏移量

1.立即数

2.寄存器

3.寄存器移位

 

4.将基址表示的加载到寄存器,基址=基址+偏移量

1.立即数

2.寄存器

3.寄存器移位

 

 

单寄存器字和无符号字节的加载,存储指令

 

 

 

单寄存器半字和有符号字节的加载,存储指令

 

加载指令

语法格式

LDR{cond}H    Rd, <地址模式>

功能:Rd<-  <地址模式>,高16bit用0填充

 

LDR{cond}SH  Rd, <地址模式>

功能:Rd<-  <地址模式>,高16bit用符号位填充

 

LDR{cond}SB   Rd, <地址模式>

功能:Rd<-  <地址模式>,高24bit用符号位填充

使用示例

LDRH     R1, [R0]

R0=0x20008000

R1=0x4800

 

LDRSH      R8, [R3, #2]

LDREQH    R12, [R13, #-6]

LDRSB   R7, [R6, #-1]!

LDRH    R3, [R9], #2

LDRSB  R1, [R2], R3

LDRH      PC,  [R0]                              @×

LDRH      R0,  [R0], #4                         @×

LDRSB     PC, [R0]                               @×

LDRSB     R0, [R0], #4                         @×

不要以PC作为目标寄存器用在加载半字和字节的加载指令中

在基址要发生变化的指令中,基址寄存器和目标寄存器不要相同的

 

语法格式

STR{cond}H  Rd,<地址模式>

 

使用示例

STRH    R1, [R0]

STRH    R8, [R3, #2]

STREQH  R12, [R13, #-6]

STRH   R7, [R6, #-2]!

STRH    R3, [R9], #2

STRH  R1, [R2], R3

STRH      PC, [R0]                              @×

STRH      R0, [R0], #4                         @×

STRH      R7, [R6, #-1]                           @ ?

半字读写时,指定的地址必须半字对齐,地址整除2

 

基址+偏移量

偏移量:立即数(由8bit来表示),寄存器

 

1 .零偏移

LDRSH  R0, [R1]    

 R0<-[R1]的低16bit   R0的高16bit用符号位填充

 

2.[<Rn>, #+/-<offset_8>]

LDRH  R0, [R1, #0x04]

 

3.[<Rn>, +/-<Rm>]

LDRSB R0,[R1, R2]

 

 

 

4.[<Rn>, #+/-<offset_8>]!

LDRH   R0, [R1, #0x08]!

 

5.[<Rn>, +/-<Rm>]!

LDRSB R0,[R1, R2]!

 

 

6. [<Rn>],#+/-<offset_8>

LDRSH  R0, [R1], #0x4

 

7.[<Rn>], +/-<Rm>

LDRSH  R0, [R1], R2

 

 

 

单寄存器字和无符号字节存储加载指令

地址模式:

基址+偏移量

立即数(12bit)

寄存器

寄存器移位

 

单寄存器半字和有符号字节存储加载指令

地址模式:

基址+偏移量

立即数(8bit)

寄存器

 

多寄存器存储加载指令

多寄存器加载指令  LDM

LDM{cond}{addressing_mode}  Rb{!}, < Reglist >{^}

功能:将Rb基址中数据加载到Reglist表示的寄存器列表中

 

LDMIA / STMIA        后增加

 LDMIB / STMIB         先增加

 LDMDA / STMDA     后减小

 LDMDB / STMDB     先减小

 

多寄存器存储指令  STM

STM{cond}{addressing_mode}  Rb{!}, < Reglist>{^}

cond  : 条件域

addressing_mode

LDMIA /STMIA     Increment After(先操作,后增加)

LDMIB /STMIB      Increment Before(先增加,后操作)

LDMDA /STMDA   Decrement After (先操作,后递减)

LDMDB /STMDB   Decrement Before (先递减,后操作)

Rb  : 基址寄存器

!  :    更新基址寄存器

Reglist:  源/目标寄存器列表(可以是16个寄存器的任何子集)

^   :   1.寄存器列表中没有PC寄存器:特权模式下使用用户模式下的寄存器

        2.寄存器列表中有PC寄存器,CPSR=SPSR,异常返回

                                          

R10:基址寄存器

{R0,R1,R4}:源操作的寄存器

 

STMDA  R10!, {R0,R1,R4}

 

 

LDMIA  R10, {R0,R1,R4}

 

R0=0x20008000    IB地址先增加,然后再加载数据

[0x20008000]=1

[0x20008004]=2

[0x20008008]=3

[0x2000800C]=4

[0x20008010]=5

LDMIB   R0! , {R1,R2,R3,R4}

R1=2

R2=3

R3=4

R4=5

R0=0x20008010

 

R0=0x20008000    IA地址后增加,先加载数据

[0x20008000]=1

[0x20008004]=2

[0x20008008]=3

[0x2000800C]=4

[0x20008010]=5

LDMIA    R0!, {R1, R2, R3,R4}

R1=1

R2=2

R3=3

R4=4

R0=0x20008010

 

LDMIA       R0!, {R1-R3}

LDMIB       R0, {R1-R3,  R7}^              @ x usr/sys

LDMDB      SP!,{R1-R3, PC}^               @ x usr/sys

LDMDB      R0, {R0-R2}

LDMDA      R15, {R1}                        @x

LDMDB      R0!,  {R0-R2}                  @x Rn值

 

 

LDM{cond}{addressing_mode}  Rb{!}, < Reglist >{^}

功能:将Rb基址中数据加载到Reglist表示的寄存器列表中

 

多寄存器存储指令  STM

STM{cond}{addressing_mode}  Rb{!}, < Reglist>{^}

 

IA  先存储或加载数据,地址后增加 

IB  地址先增加,后存储或加载数据

DA 先存储或加载数据,地址后减小

DB 地址先减小,后存储或加载数据

 

多寄存器存储加载,只操作字数据

大编号寄存器存放在高地址,小编号寄存器存放在低地址

!:基址要更新

^:1.寄存器列表中包括PC,CPSR=SPSR(异常模式下使用)

  2.寄存器列表中不包括PC,特权模式下使用用户模式寄存器

PC不做为基址寄存器

若要更新基址,基址和目标寄存器不使用相同的寄存器

 

STMIA         R0!, {R1-R3}

STMIA         SP!, {R1-R3, LR}   

STMIB         R0, {R1-R3,  R9}^        @x usr/sys

STMDB        R0, {R0-R2}

STMDB        R0!,  {R0-R2}    

STMDA        R15, {R1}                     @ x

 

 

栈的种类:

Descending stacks (减栈)

栈向内存地址减小的方向变化

 

Ascending stacks   (加栈)

栈向内存地址增加的方向变化

 

Full stacks (满栈)

栈指针指向的栈顶保存有效元素

 

Empty stacks (空栈)

栈指针指向的栈顶未保存有效元素

 

综合以上两种特点,有以下4种栈

FD(Full       Descending) 满减栈

ED(Empty  Descending)   空间栈

FA(Full        Ascending) 满加栈

EA(Empty  Ascending)    空加栈

 

STMFD   (Push) [多寄存器存储 - STMDB]

 LDMFD  (Pop) [多寄存器加载 - LDMIA]

 

STMDB  入栈

LDMIA   出栈

 

…….

MOV  R0, #0

MOV  R1,#1

BL    loop   CPU自动将ADD指令地址存放LR

ADD  R3,R4

loop:

    STMFD sp!, {r4-r7, lr}

SUBR4, #1

  …..

    LDMFD sp!, {r4-r7, pc}

 

STMFD(STMDB\Push):入栈

根据满减栈原则,先减地址,后入栈,高地址存大编号寄存器的原则,依次入栈,栈顶指针永远指向有效元素。如果不先减地址,则将原栈顶有效元素覆盖。

 

LDMFD(LDMIA\Pop):出栈

根据满减栈原则,先出栈,后加地址,依次出栈,栈顶指针永远指向有效元素。如果不先出栈,则将丢失一个有效元素。

 

 

MRS程序状态寄存器读指令

MRS指令语法格式

MRS{cond}    Rd, psr

cond 条件码 

Rd目标寄存器(不能是R15)

Psr  程序状态寄存器(CPSR,SPSR)

MRS{<cond>}  <Rd>, CPSR

MRS{<cond>}  <Rd>, SPSR

 

示例:

MRS    R0, CPSR  ;将CPSR状态寄存器读取,保存到R0中

MRS    R1, SPSR  ;将SPSR状态寄存器读取,保存到R1中

 

MSR程序状态寄存器写指令

指令的语法格式如下

MSR{<cond>}CPSR_<fields>, #<immediate_8>

MSR{<cond>}CPSR_<fields>, <Rm>

MSR{<cond>}SPSR_<fields>, #<immediate_8>

MSR{<cond>}SPSR_<fields>, <Rm>

 

 

MRS   R0, CPSR        @ Read the CPSR

BIC    R0, R0, #0xF0000000  @Clear the N, Z, C and V bits

MSR   CPSR_f, R0      @ Update the flag bits in the CPSR

                         @ N, Z, C and V flagsnow all clear

MRS    R0, CPSR        @Read the CPSR

ORR    R0, R0, #0x80   @Set the interrupt disable bit

MSR    CPSR_c, R0 @ Update the control bits in the CPSR

                   @ interrupts (IRQ) nowdisabled

 

MRS    R0,CPSR   @Read the CPSR

BIC     R0,R0, #0x1F   @ Clear the mode bits

ORR    R0,R0, #0x11  @ Set the mode bits to FIQmode

MSR   CPSR_c, R0  @ Update the controlbits in the CPSR

                     @ now in FIQ mode

 

MSR   CPSR_c,#0x11   

                 00010001

模式位改为FIQ,T位ARM状态,中断都被打开

只有确定了当前IFTmode需要改成一个确定的值时,才用此方法,否则,

 

-------------------------------------------------------------------------------------------------------------

伪指令:

ARM伪指令不属于ARM指令集中的指令。

定义这些指令可以使ARM汇编程序设计变得更方便。

ARM伪指令可以像其他ARM指令一样使用。

汇编器会自动用一条或多条ARM指令替换ARM伪指令。

ARM的伪指令包括

(1)ADR      小范围地址加载伪指令

(2)ADRL   中等范围地址加载伪指令

 

(3)LDR     大范围地址加载伪指令(两种写法)

(4)NOP    空指令伪指令

 

 

小范围地址加载伪指令 ADR

语法格式

ADR{cond}  register, expr

cond:条件码

register:目标寄存器,如:R0等

expr:地址表达式(相对于pc或寄存器而言,以PC或者寄存器为基址,一般以PC为基址)

加载地址范围

地址字对齐时: +/-1020 bytes(255×4)

地址非字对齐时:+/-255bytes

被编译器编译成一条ADD或者SUB指令

 

...

     ADR   R1, Delay   

     ...

Delay:

    MOV    R0, R14

    ...

 

      ...

0x20  ADD   R1, PC,#0x3c  R1=PC+0x3C=0x28+0x3C

                                  =0x64

      ...

      ...

0x64  MOV  R0, R14

      ...

 

语法格式

ADRL{cond}  register, expr

cond:条件码

register:目标寄存器,如:R0等

expr:地址表达式(相对于pc或寄存器)

加载地址范围

地址字对齐时: -256K~256K

地址非字对齐时: -64K~64K

 

LDR伪指令

语法格式

LDR{cond}  register,=[expr | label_expr]

从指令位置到文字池的偏移量必须小于4KB

示例

    ...

    LDR     R1, =TestData //将0x12345678的地址给R1

    LDR     R0, [R1] //将该地址中的数据加载到R0

    ...

TestData:

           .word  0x12345678

 

示例2

LDR pc, =label 

 

语法格式

LDR{cond}   register, label_expr

从指令位置到文字池的偏移量必须小于4KB

示例

     ...

    LDR     R1, TestData 直接将0x12345678给R1

    ...

TestData:

           .word  0x12345678

示例2

              LDR   pc, jmp_table  

   jmp_table:

                .word   func_addr

 

BL

 

NOP伪指令在汇编时将会被代替成ARM中的空操作,比如可能是“MOV  R0,R0”指令等。NOP可用于延时操作

示例   

    MOV    R1,#0x1234

Delay:

    NOP    

    NOP

SUBS    R1,R1,#1 

    BNE    Delay;

    MOV   PC,LR

 

LDR  R0,[R1]

----------------------------------------------------------------------------------------------------------

总结:

(1)单寄存器存储加载

 

(2)多寄存器存储加载(IA IB DA DB )

(3)栈(满减栈 DB IA)

(4)状态寄存器的读写命令

(5)伪指令

明天:

(1)伪操作

(2)C和汇编的混合编程

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值