weiqi7777

cortex-a8裸机系列:第三章 ARM汇编指令

1
阅读(763) 评论(0)

(汇编)指令是CPU机器指令的助记符,经过编译后会得到一串10组成的机器码,可以由CPU读取执行。

(汇编)伪指令本质上不是指令(只是和指令一起写在代码中),他是由编译器环境提供,目的是用来指导编译过程,经过编译后伪指令最终不会生成机器码。

 

 

8种寻址方式

Ø  寄存器寻址    mov r1, r2

Ø  立即寻址      mov r0, #0xff

Ø  寄存器移位寻址  mov r0,r1,lsl #3

Ø  寄存器间接寻址  ldr r0,[r2]

Ø  基址变址寻址    ldr r1,[r2,#4]

Ø  多寄存器寻址    ldmia r1!, {r2-r7,r12}

Ø  堆栈寻址        stmfd sp!, {r2-r7,lr}

Ø  相对寻址        beq flag

 

 

指令后缀

Ø  统一指令经常附带不同后缀,变成不同的指令

Ø  Bbyte 功能不变,操作长度变为8

Ø  Hhalf word)功能不变,操作长度变为16

Ø  Ssigned)功能不变,操作数变成有符号数

Ø  SS标志)功能不变,影响CPSR标志位

 

 

clip_image002

 

 

条件执行后缀

clip_image004            

 

 

 

比较指令:

比较指令用来比较2个寄存器中数据,比较指令不加后缀S,就会影响CPSR的标志位

cmp 两个寄存器数据一样, 标志位Z1

cmn 判断两个数是否互补 

tst   测试某些位是否为0,为0Z1       tst r0 #0xf   r0bit0-bit3是否全为0

teq   两个数异或,

 

CPSR访问指令

mrs msr

 

跳转指令

B   直接跳转

Bl   跳转,保存返回地址

Bx   跳转同时切换到ARM模式。一般用于异常处理的跳转

 

 

访存指令

单个字/半字/字节访问  ldr/str

多字批量访问  ldm/stm

swp r1, r2, [r0]  内存和寄存器互换指令  r0的内存地址数据读取到r1中,并把r2的数据写入到r0的内存地址

swp r1, r1, [r0]  实现了r0的内存地址数据和r1寄存器数据互换

 

 

软中断指令

swi software interrupt

软中断指令用来实现操作系统中系统调用

 

 

多寄存器访问指令

    stmia sp, {r0 - r12}

    r0存入sp指向的内存处(假设为0x30001000);然后地址+4(即指向0x30001004),将r1存入该地址;然后地址再+4(指向0x30001008),将r2存入该地址······直到r12内容放入(0x3000130),指令完成。

    一个访存周期同时完成13个寄存器对一段地址空间的写操作

 

    ldmia  sp, {r0 - r12}

    sp指向的内存处(假设为0x30001000)的数据写入到r0中;然后地址+4(即指向0x30001004),将地址数据写入到r1;然后地址再+4(指向0x30001008),将地址数据写入到r2······直到(0x3000130)地址数据写入到r12中,指令完成。

    一个访存周期同时完成13个寄存器对一段地址空间的读操作

 

8种后缀

    iaincrease after)先传输,再地址+4

    ibincrease before)先地址+4,再传输

    dadecrease after)先传输,再地址-4

    db                先地址-4,再传输

    fdfull decrease)满递减堆栈

    edempty decrease)空递减堆栈

    fa······· 满递增堆栈

    ea·······)空递增堆栈

^作用:

       ldmfd    sp!, {r0 - r6, pc}^

   在目标寄存器中有pc时,会同时将SPSR写入到CPSR

 

 

 

总结:

l  批量读取或写入内存时要用ldm/stm指令

 

 

GNU伪指令

.global  _start                      _start外部链接属性

.section  .text                      制定当前的段为代码段

.ascii .byte .short .long .word

.quad  .float  .string                 定义数据

.align 4                              16字节对齐

.balignl  16 0xabcdefgh                16字节对齐填充

.equ                                类似于C中宏定义

 

 

.balignl  16, 0xdeadbeef

B表示位填充, align 表示要对齐, l表示long,以4字节为单位填充;16表示16字节对齐; 0xdeadbeef是用来填充的原料

 

0x0000_0008:  .balignl  16, 0xdeadbeef

0x0000_000c:   保存0xdeadbeef

0x0000_0010:  下一条指令

 

.balignl  32, 0xdeadbeef

0x0000_0008:  .balignl  32, 0xdeadbeef

0x0000_000c:   保存0xdeadbeef

0x0000_0010:   保存0xdeadbeef(继续填充,直到32字节)

0x0000_0014:  下一条指令

 

 

.arm       / .code32       声明以下的代码是ARM指令

.thumb /.code16         声明以下的代码是thumb指令

 

 

ldr   大范围的地址加载指令

adr   小范围的地址加载指令

adrl   中等范围的地址加载指令

nop   空操作

 

ldr指令     ldr  r0 #0xff

ldr伪指令   ldr  r0 =0xff

 

 

adrldr

l  adr编译时会被一条subadd指令替代,而ldr编译时会被一条mov指令替代或者文字池方式处理

l  adr总是以PC为基准来表示地址,因此指令本身和运行地址有关,可以用来检测程序当前的运行地址在哪里

l  ldr加载的地址和链接时给定的地址有关,由链接脚本决定。

因此,adr加载的是相对地址(运行时决定),ldr加载的是绝对地址(链接时决定),因此可以通过adrldr加载的地址来判断当前程序是否在链接时制定的地址运行