我正在读的这本书说这个函数有一个局部变量。它还说,这个函数有一个局部变量很重要,因为它是递归的。也许我只是盲目,或者我不了解局部变量在汇编语言中是如何工作的,但我看不到它。
.type factorial, @function
factorial:
push %rbp # Save old base pointer.
mov %rsp, %rbp # Copy stack pointer to base pointer.
mov 16(%rbp), %rax # Save the argument in %rax.
cmp $1, %rax # End of the factorial.
je end_factorial
dec %rax # Decrement %rax.
push %rax # Push onto stack for next call to factorial.
call factorial
mov 16(%rbp), %rbx # %rax has return value, so load arg into %rbx.
imul %rbx, %rax # Multiply that by result of last call to factorial.
end_factorial:
# Restore stack pointer and base pointer to where they were
# before function call.
mov %rbp, %rsp
pop %rbp
ret寄存器可以被认为是局部变量吗?我认为局部变量是用类似sub $8, %rsp的东西实现的。
发布于 2012-10-21 02:20:10
局部变量不是通过它们的实现来定义的,而是通过它们的语义来定义的。
一种定义
一个变量是局部,如果函数的每次调用都有它自己的独立值,这就是为什么你可以说变量的值是“函数的局部”。
由于此行为可以通过使用寄存器来实现,因此这是一个完全有效的实现。
保存和恢复局部变量
但是,由于某些寄存器被认为是调用方保存的,因此在调用嵌套函数之前,可能必须将这些值放入堆栈中,否则这些值将丢失。在从嵌套调用返回到原始函数时,然后可以将值从堆栈恢复到寄存器中。
如前所述,访问寄存器比访问堆栈快得多。因此,在任何可能的情况下,它们都比主存储器更好。
然而,我不知道为什么它不能只做imul 16(%rbp), %rax而不做额外的移动操作。毕竟,imul指令允许源操作数在内存中。
发布于 2012-10-21 02:08:33
寄存器是放置局部变量的完全有效的位置。事实上,它比内存更受欢迎,因为访问速度要快得多。我修改了我的LLVM演示页面,以便在http://ellcc.org/demo/上编译这个阶乘算法。对于x86-64,它提供了
.file "/tmp/webcompile/_23578_0.c"
.text
.globl fact
.align 16, 0x90
.type fact,@function
fact: # @fact
.cfi_startproc
# BB#0: # %entry
movl $1, %eax
cmpq $2, %rdi
jl .LBB0_2
.align 16, 0x90
.LBB0_1: # %if.end
# =>This Inner Loop Header: Depth=1
imulq %rdi, %rax
decq %rdi
cmpq $1, %rdi
jg .LBB0_1
.LBB0_2: # %return
ret
.Ltmp0:
.size fact, .Ltmp0-fact
.cfi_endproc请注意,在这种情况下,编译器摆脱了递归,只使用寄存器进行计算。
https://stackoverflow.com/questions/12990878
复制相似问题