我试图理解递归函数调用期间的汇编代码。
#include<stdio.h>
int recursive(int no){
if(no > 1){
no--;
recursive(no);
printf("\n %d \n",no);
}
else if(no == 1){
return 1;
}
}
int main(){
int a = 10;
recursive(a);
return 0;
}
反汇编:
.file "sample2.c"
.section .rodata
.LC0:
.string "\n %d \n"
.text
.globl recursive
.type recursive, @function
recursive:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
cmpl $1, 8(%ebp)
jle .L2
subl $1, 8(%ebp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call recursive
movl $.LC0, %eax
movl 8(%ebp), %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call printf
jmp .L5
.L2:
cmpl $1, 8(%ebp)
jne .L5
movl $1, %eax
movl %eax, %edx
movl %edx, %eax
jmp .L4
.L5:
.L4:
leave
ret
.size recursive, .-recursive
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
movl $10, 28(%esp)
movl 28(%esp), %eax
movl %eax, (%esp)
call recursive
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
.section .note.GNU-stack,"",@progbits
我可以理解 .LC0 始终保存字符串文字。但我不知道它的真正含义是什么。想了解函数调用递归过程中的代码。 我无法理解这段汇编代码的作用,
subl $24, %esp
cmpl $1, 8(%ebp)
jle .L2
subl $1, 8(%ebp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call recursive
movl $.LC0, %eax
movl 8(%ebp), %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call printf
jmp .L5
.L2:
cmpl $1, 8(%ebp)
jne .L5
movl $1, %eax
movl %eax, %edx
movl %edx, %eax
jmp .L4
问题一: 递归函数包含 1 个参数。所以填充对齐后,它必须是8。为什么是24。
也在 .L2 中,
movl $1, %eax
movl %eax, %edx
movl %edx, %eax
jmp .L4
第二季度: 我们已经将“1”移至累加器,为什么我们要再次移至数据寄存器,然后再移回累加器。
第三季度: 我们是否从堆栈中弹出?如果用leave来出栈,那我们不是把剩下的8个栈帧都弹出了吗?
最佳答案
要回答帖子中唯一与您的标题相符的内容:
Why are we not popping out from the stack and only push instruction in the assembly.
因为leave
相当于:
movl %ebp, %esp
popl %ebp
关于c - 函数局部变量的字节分配以及 POP 指令是否仅调用一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15776575/