b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

X86-64函数调用和堆栈框架原理(2)

电脑杂谈  发布时间:2020-04-05 09:11:39  来源:网络整理

对于8个参数,可以看出最后两个参数从后到前被压入堆栈,并且前6个参数都保存到相应的参数寄存器中,这与在开始时的描述一致本文.

输入添加后的操作如下:

add:
.LFB2:
    pushq    %rbp # 保存父栈帧指针
.LCFI0:
    movq    %rsp, %rbp  # 创建新栈帧
.LCFI1:
    movl    %edi, -20(%rbp)  # 在寄存器中的参数压栈
    movl    %esi, -24(%rbp)
    movl    %edx, -28(%rbp)
    movl    %ecx, -32(%rbp)
    movl    %r8d, -36(%rbp)
    movl    %r9d, -40(%rbp)
    movl    -24(%rbp), %eax
    addl    -20(%rbp), %eax
    addl    -28(%rbp), %eax
    addl    -32(%rbp), %eax
    addl    -36(%rbp), %eax
    addl    -40(%rbp), %eax
    addl    16(%rbp), %eax
    addl    24(%rbp), %eax
    movl    %eax, -4(%rbp)
    movl    -4(%rbp), %eax
    leave
    ret

add的前两个指令实现了新堆栈框架的创建. 然后,寄存器中的函数调用参数被压入堆栈. 如本文前面所述,由于参数的内存地址可以在子例程中使用,因此无法在寄存器中访问这些参数. 在这里,参数被压入堆栈,这恰好证实了我们先前的猜想.

24帧和25帧的视觉效果_栈帧_扩展帧和标准帧

将参数压入堆栈时,我们发现未使用诸如push之类的指令,并且未调整%esp指针的值. 而是使用-N(%rbp)之类的指令来使用新的堆栈空间. 这种使用“基地址+偏移量”来使用堆栈的方式实际上与直接使用%esp指向堆栈的顶部相同.

有两个与编译器的具体实现有关的问题: 首先,在上述程序中,未使用-8(%rbp)和-12(%rbp)地址,并且这两个地址之前的地址-使用4(%rbp)和更高的-16(%rsp),这可能是由于编译器的特定实现. 另一个是以下两个指令:

    movl    %eax, -4(%rbp)
    movl    -4(%rbp), %eax

首先将%eax的值分配给-4(%rbp),然后将该值反转一次,以为编译器可能会出于一般性考虑而这样做. 以上两个问题有待进一步研究.

当add函数返回时,返回的结果将存储在%eax中,%rbp和%rsp将被调整为指向main的堆栈帧,然后将执行main函数中的以下指令:

movl    %eax, -8(%rbp)  # 保存 add 函数返回值到栈中,对应 C 语句 int sum = add(...)
movl   -12(%rbp), %eax  # 恢复 call save 寄存器 %eax 的值,与调用add前保存 %eax 相对应 
movl    %eax, -4(%rbp) # 对应 C 语句 m = k,%eax 中的值就是 k。
movl    $0, %eax  # main 函数返回值
leave   # main 函数返回
ret

可以看出,当add函数返回时,返回值保存在%eax中. 使用返回值后,将恢复呼叫者保存寄存器%eax的值. 此时,主堆栈框架与调用add之前的框架完全相同.

应注意,在调用add之前,在main中执行诸如subq 48,%rsp之类的指令. 原因是在调用add之后,main中没有调用其他函数,而是执行了两个赋值语句. 直接从main返回之后. 两条指令在main的结尾处离开和ret直接覆盖%rsp的值并返回main的父堆栈帧. 如果先调整主堆栈帧的%rsp值,然后离开然后覆盖%rsp值,则意味着该调整是多余的. 因此,更合理的做法是,在main中添加收益后,省略对rsp的调整,并使用休假直接覆盖rsp.

本文介绍了从汇编级别调用X86-64体系结构中的函数时堆栈帧切换的原理. 理解这些底层细节对于理解程序的运行非常有帮助. 并且在许多当前程序中,为了实现程序的有效运行,使用了汇编语言. 在了解了函数堆栈框架切换的原理之后,对于理解这些程序集也很有帮助.

在下一篇文章中,我们将详细介绍libco库中以汇编语言实现的协程的上下文切换. 本文可以作为理解协程上下文切换的基础.

结局.

我是我,一只企鹅疾驰.

我是我,不同的烟花.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-164560-2.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    每日福利
    热点图片
    拼命载入中...