汇编(二)

2019-04-04  本文已影响0人  昵称是乱起的

1. bl指令

2. bl指令练习

2.1. 在xocode中新建一个汇编文件
image.png

汇编是.s结尾


image.png
2.2. 汇编代码

这是arm64的汇编,一定要在5s以上的真机上运行

.text                //存储在代码段
.global _A,_B        //暴露A,B给外部调用

_A:
    mov x0,#0xa      //x0=0xa
    mov x1,#0x00     //x1=0x00
    add x1,x0,#0xff  //x1=x0+0xff
    mov x0,x1        //x0=x1
    bl _B            //跳转_B
    mov x0,#0x00
    ret
_B:
    add x0,x0,#0x10  //x0=x0+ 0x10
    ret

汇编在Xcode中是会参与编译的


image.png

main.m中调用


image.png

这样打断点是断不住的

image.png
main.m中打断点。Debug->Debug Workflow->Always Show Disaseembly显示汇编
image.png
再运行,会断在这里
image.png
在lldb中s进入函数中
image.png
image.png
选中这个可以看到寄存器相关的
image.png
n单步往下执行可以看到寄存器的值已经改变
image.png
image.png

3. 函数调用栈

3.1. 栈:是一种具有特殊的访问方式的存储空间(后进先出,LIFO)
image.png
3.1. SP和FP寄存器
3.2. 函数调用栈
.text
.global _A,_B

_A:
    mov x0,#0xa
    mov x1,#0x00
    add x1,x0,#0xff
    mov x0,x1
    bl _B
    mov x0,#0x00
    ret
_B:
    sub sp,sp,#0x20       //拉伸0x20(32字节)空间
    stp x0,x1,[sp,#0x10]  //将x0,x1写入sp+#0x10内存中
    ldp x1,x0,[sp,#0x10]  //将sp+#0x10这段内存的数据加载到x1,x0中
    add sp,sp,#0x20       //栈平衡
    ret

断点查看,memory read sp,读取的32字节的数据

image.png
n走一步,拉伸栈空间,读取sp的值,sp的值已经改变,里面的数据可能是以前用过的,等会就会被覆盖
image.png
发现数据已经写入了,前面x0,后面x1
image.png
n下一步,x0,x1的值已经交换
image.png
栈空间平衡
image.png

4. bl和ret指令

上面写的bl指令是有问题的,main函数中这样执行一下,发现没有打印B,


image.png

打断点进去汇编里面看看,注意这个lr和pc


image
bl进B函数后,发现lr的值是上面A中bl的下一条指令,pc是将要执行的下一条指令
image.png

继续ni,直到ret后回到A函数,发现lr和sp的值一样,由此可以发现bl指令之所以能够跳转回去,是lr记录了跳转之前的bl的下一句指令


A
继续执行ni,发现lr的值始终始终不变,,执行完ret后,pc的值又跟lr一样了,程序在这一直死循环了,原因是main函数bl进A的时候lr存的值被覆盖掉了,
image.png
至此得出结论,bl进新函数后,要保存下lr的值,bl其他函数回来后要把lr的值重新取一下,把代码改成这样
.text
.global _A,_B

_A:
    mov x0,#0xa
    mov x1,#0x00
    add x1,x0,#0xff
    mov x0,x1
//存储lr(x30)
    sub sp,sp,#0x10
    str x30,[sp]
////////////
    bl _B
    mov x0,#0x00
//取出lr
    ldr x30,[sp]
    add sp,sp,#0x10
////////////
    ret
_B:
    sub sp,sp,#0x20
    stp x0,x1,[sp,#0x10]  //将x0,x1写入sp+#0x10内存中
    ldp x1,x0,[sp,#0x10]  //将sp+#0x10这段内存的数据加载到x1,x0中
    add sp,sp,#0x20
    ret

执行,输出AB了,问题解决


image.png

上面的存储和取出的代码还可以优化成1句,表达的意思都是一样的

//存储lr(x30)
    sub sp,sp,#0x10
    str x30,[sp]
可以改成
str x30,[sp,#-0x10]!

//取出lr
    ldr x30,[sp]
    add sp,sp,#0x10
可以改成
ldr x30,[sp],#0x10

5. 函数的参数和返回值

5.1. main函数中定义一个9个参数的函数,然后断点查看汇编
image.png

来分析一下栈内存


image.png image.png

将上面的栈结构画成这张图更直观


image.png

函数的返回值进入到test函数里面


image.png
5.1. main函数中定义一个返回结构体的函数来看返回值是操作的
image.png

main函数栈空间


image.png

getStr函数栈


image.png

6. 总结

上面主要学习了bl指令和函数的堆栈,通过一些堆栈练习了解寄存器的存储,学习了函数的参数和返回值是如何进行操作。

上一篇下一篇

猜你喜欢

热点阅读