因子大会x86

时间:2015-08-27 12:04:15

标签: linux assembly x86

我有这个汇编代码(使用gcc -m32编译的Linux 32Bit),我真的不明白为什么我的程序不起作用。

.data

    .bla:
            .ascii "%d\n\0"

    .globl main

    .text

    main:           pushl $4
                    call factorial
                    movl $1, %eax
                    ret
    factorial:
                    push %ebp
                    movl %esp, %ebp
                    movl 8(%ebp), %ecx
                    cmpl $1, %ecx
                    jg .rek
                    movl $1, %eax
                    movl %ebp, %esp
                    pop %ebp
                    ret

    .rek:
                    decl %ecx
                    pushl %ecx
                    call factorial
                    addl $4, %esp
                    movl 8(%ebp), %ecx
                    imull %ecx, %eax
                    pushl %eax
                    pushl $.bla
                    call printf
                    addl $8, %esp
                    movl %ebp, %esp
                    pop %ebp
                    ret

不幸的是,每次发生分段错误+大于4的参数都不起作用。

当我用“3”运行程序时,这应该是我的堆栈:

3
ret add
ebp
2
ret add
ebp
1
ret add
ebp

当我到达递归的底部时,我将保存在eax中的返回值乘以8(%ebp),这应该是下一个值。

我非常感谢您提供的任何帮助。

1 个答案:

答案 0 :(得分:2)

我看到的三个问题。

1)您的call maine(我假设这是一个拼写错误,您的意思是main)应为call factorial

2)在main程序中,您无法恢复堆栈指针。

3)您的printf来电会修改%eax并覆盖factorial之前的结果。

修复计划:

.data

.bla:
        .ascii "%d\n\0"

.globl main

.text

main:   pushl $5
        call factorial
        addl $4, %esp         # ADDED THIS
        movl $1, %eax
        ret
factorial:
        push %ebp
        movl %esp, %ebp
        movl 8(%ebp), %ecx
        cmpl $1, %ecx
        jg .rek
        movl $1, %eax
        movl %ebp, %esp
        pop %ebp
        ret
.rek:
        decl %ecx
        pushl %ecx
        call factorial   # FIXED THIS
        addl $4, %esp
        movl 8(%ebp), %ecx
        imull %ecx, %eax
        pushl %eax            # ADDED THIS - SAVE RETURN VALUE
        pushl %eax
        pushl $.bla
        call printf
        addl $8, %esp         # MODIFIED THIS
        pop %eax              # ADDED THIS (restore eax result)
        movl %ebp, %esp
        pop %ebp
        ret