汇编实现函数调用

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
相关推荐
我在人间贩卖青春8 天前
汇编之伪指令
汇编·伪指令
我在人间贩卖青春8 天前
汇编之伪操作
汇编·伪操作
济6178 天前
FreeRTOS基础--堆栈概念与汇编指令实战解析
汇编·嵌入式·freertos
myloveasuka8 天前
汇编TEST指令
汇编
我在人间贩卖青春8 天前
汇编编程驱动LED
汇编·点亮led
我在人间贩卖青春8 天前
汇编和C编程相互调用
汇编·混合编程
myloveasuka9 天前
寻址方式笔记
汇编·笔记·计算机组成原理
请输入蚊子9 天前
《操作系统真象还原》 第六章 完善内核
linux·汇编·操作系统·bochs·操作系统真像还原
myloveasuka9 天前
指令格式举例
汇编·笔记·计算机组成原理
我在人间贩卖青春10 天前
汇编之分支跳转指令
汇编·arm·分支跳转