c - 函数局部变量的字节分配以及 POP 指令是否仅调用一次

标签 c unix assembly x86

我试图理解递归函数调用期间的汇编代码。

#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/

相关文章:

assembly - 汇编器什么时候使用像 R_X86_64_32S 这样的符号扩展重定位而不是像 R_X86_64_32 这样的零扩展更好?

c - 如何将数据与内联汇编进行比较?

c - 在 Code 128 条码中编码扩展 ASCII 字符

c - 替换纯 C 中的链接器部分

c - 在 C 中用等效的 HTML 实体替换字符/符号

unix - cat 按什么顺序选择要显示的文件?

c - 控制台中的全宽进度条

linux - 如何在 Perl 中使用记录分隔符

c++ - 如何测试数字是否以值结尾?

windows - PE : Relation between SizeOfRawData and VirtualSize fields of the section header