美文网首页
汇编学习(5),函数,栈帧

汇编学习(5),函数,栈帧

作者: android小奉先 | 来源:发表于2022-12-04 18:48 被阅读0次

本篇介绍

本篇介绍下汇编中的函数,栈帧内容。

函数

汇编也支持函数调用,如下是一个例子:

extern printf
section .data                           
    radius  dq  10.0                
    pi      dq  3.14                
    fmt     db  "The area of the circle is %.2f, radius is %.2f",10,0
section .bss                            
section .text                                               
    global main                     
;----------------------------------------------
main:
push    rbp
mov     rbp, rsp 
    call surface            ; call the function
    mov rdi,fmt             ; print format
    movsd xmm1, [radius]    ; move float to xmm1
    mov rax,2               ; surface in xmm0
    call printf
        leave
ret
;----------------------------------------------
surface:
push    rbp
mov     rbp, rsp        
    movsd xmm0, [radius]    ; move float to xmm0
    mulsd xmm0, [radius]    ; multiply xmm0 by float
    mulsd xmm0, [pi]        ; multiply xmm0 by float
leave
ret             

输出:
The area of the circle is 314.00, radius is 10.00

使用call + 标号就可以实现函数调用,对于浮点,返回值会通过xmm0传递。

这儿又出现了一个leave指令,leave就等同于 mov rsp,rbp,pop rbp。

函数也可以拥有自己的代码段和数据段,如下面的例子:

; function2.asm
extern printf
section .data                           
    radius  dq  10.0                                
section .bss                            
section .text
area:
    section .data
        .pi dq  3.141592654 ; local to area
    section .text 
push rbp
mov rbp, rsp
        movsd xmm0, [radius]
        mulsd xmm0, [radius]
        mulsd xmm0, [.pi]
leave
ret
circum:
    section .data
        .pi dq  3.14        ; local to circum
    section .text
push rbp
mov rbp, rsp    
        movsd xmm0, [radius]
        addsd xmm0, [radius]
        mulsd xmm0, [.pi]
leave
ret
circle:
    section .data
        .fmt_area   db  "The area is %f",10,0
        .fmt_circum db  "The circumference is %f",10,0
    section .text
push rbp
mov rbp, rsp        
        call area   
        mov rdi,.fmt_area
        mov rax,1           ; area in xmm0
        call printf
        call circum
        mov rdi,.fmt_circum
        mov rax,1           ; circumference in xmm0
        call printf
leave
ret
    global main                     
main:
    mov rbp, rsp; for correct debugging
push rbp
mov rbp, rsp
    call circle
leave
ret

输出:
The area is 314.159265
The circumference is 62.800000

这儿可以看到在函数内部也可以定义数据段,用来存放局部变量。

栈帧

对于intel处理器,在调用函数的时候需要保证rsp是16字节对齐的,这样设计是为了更好的支持SIMD。那体现到代码上是怎样呢?可以看下如下的代码:

extern printf
section .data                           
    fmt db  "2 times pi equals %.14f",10,0 
    pi  dq  3.14159265358979
section .bss                            
section .text
func3:
    push rbp
        movsd   xmm0, [pi]
        addsd   xmm0, [pi]
        mov     rdi,fmt
        mov     rax,1       
        call    printf  ; print a float
    pop rbp
    ret
func2:
    push rbp
        call    func3   ; call the third function
    pop rbp
    ret
func1:
    push rbp
        call    func2   ; call the second function
    pop rbp
    ret

    global main
main:
    push rbp
        ;push rbp ; for align 16 byte, uncomment it will cause crash
        call func1  ; call the first function
        ;pop rbp
    pop rbp
    ret

结果:
2 times pi equals 6.28318530717958

如果把main中注释的代码去掉,那么就会crash,因为这时候调用func1时 rsp就不是16字节对齐的。这儿可以单步看看:


image.png

这时候rsp没有16字节对齐,执行push rbp后,就会对齐。
这就是prologue和epilogue的一个作用,保证调用函数时的rsp 16字节对齐。

本来在调用main函数之前rsp是16字节对齐的,可是在调用main时候,由于会将返回地址压栈,这时候rsp就不是16字节对齐了,就需要prologue中再次执行一个进栈操作,就可以保证是对齐的了。

相关文章

  • 汇编学习(5),函数,栈帧

    本篇介绍 本篇介绍下汇编中的函数,栈帧内容。 函数 汇编也支持函数调用,如下是一个例子: 使用call + 标号就...

  • 崩溃分析汇编基础

    崩溃分析汇编基础 栈、调用栈、栈帧 栈 在当今多数计算机体系架构中,函数的参数传递、局部变量的分配和释放都是通过操...

  • 汇编代码注入

    分析汇编代码 形成栈帧不多解释,CreateRemoteThread远程创建线程函数的时候,第五个参数会压入远程程...

  • 巧用函数栈实现栈的反转

    一、函数栈 函数的调用过程其实就是一个压栈的过程,在函数栈中,每个函数所占空间成为一个 栈帧。栈帧中保存着函数的形...

  • 栈帧与函数调用流程(内存)---- 8086处理器

    栈帧:一个函数执行的环境,一个栈帧代表一个函数 栈帧结构: 一组栈帧寄存器-->SP局部变量bp以前的值-->BP...

  • 汇编(八)

    现场保护 平栈内:外平栈.png *现场保护 函数调用 xcode函数汇编

  • 宏、普通函数、内联函数之间的区别

    普通函数 调用时向栈中push函数帧,调用结束后pop函数帧。编译器会在函数调用语句的前后,插入入栈和出栈的辅助代...

  • 5. linux下的栈帧分析

    @toc 1.linux下的栈帧分析2. 栈帧 1. 栈帧 每一次函数的调用,都会在调用栈上维护一个独立的栈帧(s...

  • 8086汇编(18)栈帧

    栈帧 1、栈帧(Stack Frame Layout) 就是一个函数执行的环境 包括:参数、局部变量、返回地址等1...

  • Python 函数的执行流程-函数递归-匿名函数-生成器

    1 函数的执行流程 函数的执行需要对函数进行压栈的,什么是压栈呢,简而言之就是在函数执行时在栈中创建栈帧存放需要变...

网友评论

      本文标题:汇编学习(5),函数,栈帧

      本文链接:https://www.haomeiwen.com/subject/pdtmfdtx.html