汇编实现函数调用

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
相关推荐
星栖与芯18 小时前
LiteOS-M 切换汇编逐行图解(5):HalPendSV 任务切换的现场搬运(五阶段逐行)
汇编·stm32·嵌入式硬件·harmonyos
星栖与芯1 天前
LiteOS-M 切换汇编逐行图解(4):中断三件套与 HalTaskSchedule 触发
汇编·stm32·单片机·嵌入式硬件·harmonyos
xx~t2 天前
嵌入式——ARM——汇编2
linux·汇编·arm开发·嵌入式硬件·启动代码
祖力552 天前
ARM汇编LED实验
汇编·arm·imx6ull
索端阳3 天前
ARM Day02 学习总结:ARM汇编基础核心知识点梳理
汇编·学习·arm
xx~t3 天前
嵌入式——ARM——汇编1
linux·汇编·arm开发·嵌入式硬件·arm
索端阳4 天前
初识 ARM Cortex-A7,嵌入式底层入门总结
汇编·嵌入式硬件
ThornArmor4 天前
重铸1996|肉体渲染:关节的裂缝:分段模型积木拼装与未成熟的 RSP 矩阵骨骼动画形变
c语言·汇编·c++·python·硬件架构·游戏机
星栖与芯4 天前
LiteOS-M 切换汇编逐行图解(1):汇编是什么·寄存器与栈
汇编·stm32·嵌入式硬件·harmonyos·鸿蒙系统
yume_sibai5 天前
11-Rust 不安全编程(unsafe 关键字 + 裸指针 + FFI + 内联汇编 + 内存安全保证)
汇编·安全·rust