汇编实现函数调用

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

asm 复制代码
# 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用来存放第二个参数,并且把第一计算的结果存放在栈中。

asm 复制代码
# 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
相关推荐
古井无波 202412 小时前
arm64函数源码和汇编解析(objdump)
汇编
矮油0_o1 天前
30天开发操作系统 第 12 天 -- 定时器
c语言·汇编·算法·操作系统
一品人家2 天前
win32汇编环境,怎么进行加法运算的
汇编
知困勉行的Allen3 天前
MCS-51单片机常用汇编指令和特殊功能寄存器~
c语言·汇编·数据结构·单片机·嵌入式硬件·51单片机·学习方法
kaixin_learn_qt_ing4 天前
编译与汇编
汇编·编译
雪碧透心凉_4 天前
Win32汇编学习笔记04.重定位与汇编引擎
汇编·笔记·学习
hummhumm4 天前
第8章 汇编语言--- 循环结构
java·运维·开发语言·汇编·数据结构·算法·汇编语言
湘の子5 天前
汇编语言与接口技术--跑马灯
汇编·stm32·单片机·嵌入式硬件·51单片机
肖无疾6 天前
在CE自动汇编里调用lua函数
汇编·lua·ce