汇编探索(三)

2021-08-13  本文已影响0人  沉淀纷飞

前言

    上一篇文章我们已经探索过了CPU与寄存器的一些原理和内在联系。我们知道任何高级语言方法的执行,他们的底层都是调用函数方法。但有没有想过函数的底层是怎么实现的呢?函数的调用一定涉及到了函数的调用栈,什么又是函数调用栈道呢?

栈和堆

image
    什么是是在内存中一种具有特殊访问方式的存储空间。遵循后进先出( Last In Out Firt)LIFO。栈的开口对iOS系统来说来说是高地址往低地址走。局部变量参数等这些在代码中写死的东西是放在栈空间。
sub    sp, sp, #0x40             ; 
// 拉伸0x40(64字节)空间
stp    x29, x30, [sp, #0x30]     ;
// x29\x30 寄存器入栈保护
add    x29, sp, #0x30            ;
// x29指向栈帧的底部
... 
ldp    x29, x30, [sp, #0x30]     ;
// 恢复x29/x30 寄存器的值
add    sp, sp, #0x40             ; 
// 栈平衡
ret

    从上面汇编代码可以看到栈空间操作,以及栈平衡。那什么是栈平衡呢?栈是往低地址走,通过sub减可以将地址开辟出来,通过add指令加可以将栈地址恢复这个过程称为栈平衡。

sub    sp, sp, #0x20    ;
// 拉伸栈空间32个字节
stp    x0, x1, [sp, #0x10] ;
// sp往上加16个字节,存放x0 和 x1
ldp    x1, x0, [sp, #0x10] ;
// 将sp偏移16个字节的值取出来,放入x1 和 x0

    上述汇编代码的用途其实是使用32个字节空间作为这段程序的栈空间,然后利用栈将x0x1的值进行交换。[ ...]寻址 ,把左边的值存到右边地址里面去。
sp寄存器就是一个指针一个标记,sp操作必须16字节对齐,做8字节操作会崩溃。寄存的值进行交换其实内存地址没有变化。
bl指令:将下一条指令的地址放入lr(x30)寄存器,转到标号处执行指令。
ret指令:默认使用lr(x30)寄存器的值,通过底层指令提示CPU此处作为下条指令地址。ARM64平台的特色指令,它面向硬件做了优化处理的。x30寄存器:x30寄存器存放的是函数的返回地址。当ret指令执行时刻,会寻找x30寄存器保存的地址值。在函数嵌套调用的时候,需要讲x30入栈。

上一篇 下一篇

猜你喜欢

热点阅读