当前位置: 首页 > article >正文

汇编实现函数调用

x86_64 通过将函数参数存放在栈中的方式来实现参数传递。

# PURPOSE: Program to illustrate how functions work
#          This program will compute the value of
#          2^3 + 5^2
#

# Everything in the main program is stored in registers,
# so the data section doesn’t have anything.
.section .data

.section .text

.globl _start
_start:
    push $3                                         # 将第二个参数入栈
    push $2                                         # 将第一个参数入栈
    call power                                      # 调用函数power,call会自动将函数返回地址入栈,
                                                    # 也就是下一条指令的地址
    add $16, %rsp                                   # move the stack pointer back,
                                                    # 通过移动栈顶指针的方式将保存在栈中的数据清理掉
    push %rax                                       # save the first answer before
                                                    # calling the next function
    push $2                                         # push second argument
    push $5                                         # push first argument
    call power                                      # call the function
    add $16, %rsp                                   # move the stack pointer back
    pop %rbx                                        # The second answer is already
                                                    # in %rax. We saved the
                                                    # first answer onto the stack,
                                                    # so now we can just pop it
                                                    # out into %rbx,将第二次计算的结果从栈中弹出存放到rbx寄存器中
    add %rax, %rbx                                  # add them together
                                                    # the result is in %rbx
    mov $1, %rax                                    # exit (%rbx is returned)
    int $0x80

# PURPOSE: This function is used to compute
#          the value of a number raised to
#          a power.
#
# INPUT:   First argument - the base number
#          Second argument - the power to
#          raise it to
#
# OUTPUT:  Will give the result as a return value
#
# NOTES:   The power must be 1 or greater
#
# VARIABLES:
#          %rbx - holds the base number
#          %rcx - holds the power
#
#          -8(%rbp) - 将计算后的结果放在栈中
#
#          %rax is used for temporary storage
#
.type power, @function
power:
    push %rbp                                   # 将旧的栈基址入栈
    mov %rsp, %rbp                              # 当前rsp指向旧的栈基址,获取传入参数时需要加上返回地址和旧栈基址的偏移
                                                # 因为存在两次入栈,一次是返回地址入栈,一次是rpb指针入栈
    sub $8, %rsp                                # 在栈中申请8字节用于存放计算结果的内存
    mov 16(%rbp), %rbx                          # 获取栈中传入的第一个参数,值存放在rbx
    mov 24(%rbp), %rcx                          # 获取栈中传入的第一个参数,值存放在rcx
    mov %rbx, -8(%rbp)                          # store current result

power_loop_start:
    cmp $1, %rcx                                # if the power is 1, we are done
    je end_power
    mov -8(%rbp), %rax                          # move the current result into %eax
    imul %rbx, %rax                             # multiply the current result by
                                                # the base number
    mov %rax, -8(%rbp)                          # 将计算结果更新到栈中
    dec %rcx                                    # decrease the power
    jmp power_loop_start                        # run for the next power

end_power:
    mov -8(%rbp), %rax                          # return value goes in %rax
    mov %rbp, %rsp                              # restore the stack pointer
    pop %rbp                                    # restore the base pointer
    ret

编译方式:as w_power.s -o w_power.o;ld w_power.o -o w_power
结果查看:执行w_power之后,echo $?查看计算结果。

使用专用寄存器来传递函数调用参数,rdi用来存放第一参数,rsi用来存放第二个参数,并且把第一计算的结果存放在栈中。

# PURPOSE: Program to illustrate how functions work
#          This program will compute the value of
#          2^3 + 5^2
#

# Everything in the main program is stored in registers,
# so the data section doesn’t have anything.
.section .data

.section .text

.globl _start
_start:
    mov $2, %rdi                                    # 将第一个参数存入rdi
    mov $3, %rsi                                    # 将第二个参数存入rsi
    call power                                      # 调用函数power,call会自动将函数返回地址入栈,
                                                    # 也就是下一条指令的地址
    push %rax                                       # 将第一次计算的结果存放在栈中

    mov $5, %rdi                                    # 将第一个参数存入rdi
    mov $2, %rsi                                    # 将第一个参数存入rsi
    call power
    pop %rbx                                        # 获取第一次的计算结果
    add %rax, %rbx                                  # 第一次计算结果rbx与第二次计算结果rax的值相加
                                                    # the result is in %rbx
    mov $1, %rax                                    # exit (%rbx is returned)
    int $0x80

# PURPOSE: This function is used to compute
#          the value of a number raised to
#          a power.
#
# INPUT:   First argument - the base number
#          Second argument - the power to
#          raise it to
#
# OUTPUT:  Will give the result as a return value
#
# NOTES:   The power must be 1 or greater
#
# VARIABLES:
#          %rdi - 第一个参数
#          %rsi - 第二个参数
#
#          -8(%rbp) - 将计算后的结果放在栈中
#
#          %rax is used for temporary storage
#
.type power, @function
power:
    push %rbp                                   # 将旧的栈基址入栈
    mov %rsp, %rbp                              # 当前rsp指向旧的栈基址,获取传入参数时需要加上返回地址和旧栈基址的偏移
                                                # 因为存在两次入栈,一次是返回地址入栈,一次是rpb指针入栈
    sub $8, %rsp                                # 在栈中申请8字节用于存放计算结果的内存
    mov %rdi, -8(%rbp)                          # store current result

power_loop_start:
    cmp $1, %rsi                                # if the power is 1, we are done
    je end_power
    mov -8(%rbp), %rax                          # move the current result into %eax
    imul %rdi, %rax                             # multiply the current result by
                                                # the base number
    mov %rax, -8(%rbp)                          # 将计算结果更新到栈中
    dec %rsi                                    # decrease the power
    jmp power_loop_start                        # run for the next power

end_power:
    mov -8(%rbp), %rax                          # return value goes in %rax
    mov %rbp, %rsp                              # restore the stack pointer
    pop %rbp                                    # restore the base pointer
    ret

http://www.kler.cn/a/472958.html

相关文章:

  • Spring Boot教程之四十九:Spring Boot – MongoRepository 示例
  • Linux pget 下载命令详解
  • C++语言的面向对象编程
  • spring boot 集成 knife4j
  • Qt 界面外观
  • 从零手写线性回归模型:PyTorch 实现深度学习入门教程
  • 08-1_队列的理论讲解
  • 【Uniapp-Vue3】使用ref定义响应式数据变量
  • C# 中await和async的用法(二)
  • y7000p2023AX211ubuntu20无线网卡驱动
  • 【人工智能计算机视觉】——深入详解人工智能计算机视觉之图像处理之基础图像处理技术
  • UE 5.3 C++ 管理POI 如何对WidgetComponent 屏幕模式进行点击
  • 详述 VScode wkhtmltopdf 实现 markdown 转带目录标签(导航栏)的 PDF
  • k8s里面etcd的作用
  • 后端Java开发:第十二天
  • AI大模型-提示工程学习笔记4
  • 【实用技能】如何使用 .NET C# 中的 Azure Key Vault 中的 PFX 证书对 PDF 文档进行签名
  • 【UE5 C++课程系列笔记】24——多线程基础——Async
  • MySQL - 子查询和相关子查询详解
  • 低代码平台的集成与扩展性详解
  • 【DevOps工具篇】 SonarQube详解
  • Python Json格式数据处理
  • Swift语言的网络编程
  • cp命令详解
  • JAVA学习-练习试用Java实现“从用户输入获取一个字符串,并使用replace方法将字符串中的所有空格替换为下划线”
  • 深度学习中的卷积和反卷积(一)——卷积的介绍