汇编递归过程

汇编的递归过程

习惯写C程序后,一般很少会去敲汇编代码,最近在研究系统学习方面知识,需要用到汇编,考虑到编译器是如何将C程序编译成汇编代码的,这里对于C语言中的语句(赋值,运算,选择,循环)就不着重介绍,这些对应到汇编指令相对来说简单(当然忽略了编译器是如何把C语言编译成汇编代码的实现,只研究对应问题),今天主要分析C语言中函数在汇编中的实现,因为这里面涉及到栈的问题,对于汇编语言,指令完成命令无疑就是操作地址中的操作数,对于通用寄存器来说,地址是很好确定的,而对于栈的地址,我们必须清楚的知道我们的指令对栈的操作。所以,我针对C语言中的递归函数来分析汇编指令的实现过程,这不仅学习了汇编,同时也更让我清楚的了解了C语言递归函数的实质,函数调用之间的关系。

fibonacci数列
这里写图片描述
C语言实现:

#include <stdio.h>
int fu(int x)
{
    if(x<1)
        return 1;
    else
        return fu(x-2)+fu(x-1);
}
int main()
{
    int x;
    fu(x);
    return 0;
}

机器反汇编代码:(每一步的执行都对应一条汇编指令,真正用汇编语言实现不用如此麻烦,因为,汇编语言也支持选择,循环,调用)

00401020    push   %ebp
00401021    mov    %esp,%ebp
00401023    push   %ebx
00401024    sub    $0x34,%esp
00401027    movl   $0x401150,(%esp)
0040102E    call   0x4019b4 <SetUnhandledExceptionFilter@4>
00401033    sub    $0x4,%esp
00401036    call   0x401360 <__cpu_features_init>
0040103B    call   0x401770 <fpreset>
00401040    lea    -0x10(%ebp),%eax
00401043    movl   $0x0,-0x10(%ebp)
0040104A    mov    %eax,0x10(%esp)
0040104E    mov    0x402000,%eax
00401053    movl   $0x404004,0x4(%esp)
0040105B    movl   $0x404000,(%esp)
00401062    mov    %eax,0xc(%esp)
00401066    lea    -0xc(%ebp),%eax
00401069    mov    %eax,0x8(%esp)
0040106D    call   0x40195c <__getmainargs>
00401072    mov    0x404008,%eax
00401077    test   %eax,%eax
00401079    jne    0x4010c5 <__mingw_CRTStartup+165>
0040107B    call   0x401964 <__p__fmode>
00401080    mov    0x402004,%edx
00401086    mov    %edx,(%eax)
00401088    call   0x401520 <_pei386_runtime_relocator>
0040108D    and    $0xfffffff0,%esp
00401090    call   0x401750 <__main>
00401095    call   0x40196c <__p__environ>
0040109A    mov    (%eax),%eax
0040109C    mov    %eax,0x8(%esp)
004010A0    mov    0x404004,%eax
004010A5    mov    %eax,0x4(%esp)
004010A9    mov    0x404000,%eax
004010AE    mov    %eax,(%esp)
004010B1    call   0x40134d <main>
004010B6    mov    %eax,%ebx
004010B8    call   0x401974 <_cexit>
004010BD    mov    %ebx,(%esp)
004010C0    call   0x4019bc <ExitProcess@4>
004010C5    mov    0x4050f4,%ebx
004010CB    mov    %eax,0x402004
004010D0    mov    %eax,0x4(%esp)
004010D4    mov    0x10(%ebx),%eax
004010D7    mov    %eax,(%esp)
004010DA    call   0x40197c <_setmode>
004010DF    mov    0x404008,%eax
004010E4    mov    %eax,0x4(%esp)
004010E8    mov    0x30(%ebx),%eax
004010EB    mov    %eax,(%esp)
004010EE    call   0x40197c <_setmode>
004010F3    mov    0x404008,%eax
004010F8    mov    %eax,0x4(%esp)
004010FC    mov    0x50(%ebx),%eax
004010FF    mov    %eax,(%esp)
00401102    call   0x40197c <_setmode>
00401107    jmp    0x40107b <__mingw_CRTStartup+91>
0040110C    lea    0x0(%esi,%eiz,1),%esi

汇编代码:

code segment
    ;主程序
    main proc far
        assume cs:code
start:
        mov ax,0    ;ax存储函数值,清零
        mov bx,8    ;设置函数x
        push bx     ;参数压栈
        call  digui ;ip压栈   
        ret
    main endp

    ;递归子程序
    digui proc near 
        push bp 
        mov bp,sp
        push dx     ;保存和的后一个加数
        push bx
        sub sp,2
        mov bx,(bp+4)
        cmp bx,2
        je out1
        cmp bx,1
        je out1
        sub bx,1
        mov (bp-6),bx
        call digui
        mov dx,ax   ;将和的第一个加数保存到dx,去计算后一个加数
        dec bx      ;求f(n-2)
        push bx
        call digui
        pop bx ;清空n
        add ax,dx   ;将第二个加数加到第一个加数上,即求和
        jmp out2        ;作为第二个加数的参数压栈

out1:
        mov ax,1
out2:
        add sp,2
        pop bx
        pop dx
        pop bp
        ret
    digui   endp
code ends
    end main

栈的实现过程:

参数先给到bx,把bx压栈就是把参数压栈,假设参数为5

栈值  Sp  栈操作 
n=4 fe   Push bx    
Ip  Fc  Call digui  
Bp=0000 Fa  Push bp 
Dx=0    F8  Push dx 
Bx=4    F6  Push bx 
n=3     Sub sp,2  mov (bp-6),bx 
Ip      Call digui  
Bp      Push bp 
Dx=0        Push dx 
Bx=3        Push bx 
N=2     Sub sp,2 mov (bp-6),bx  
Ip      Call digui  
Bp=f2       Push bp 
Bx=2        Push bx 
N=1     Sub sp,2 mov (bp-6),bx  
Ip      Call digui  
Bp      Push bp 
Dx      Push bx 
Bx=2        Sub sp,2 mov (bp-6),bx  
            Mov bx,(bp+4) bx=2
        Cmp bx,2   je out1  mov ax,1    Ax=1    

猜你喜欢

转载自blog.csdn.net/u010865478/article/details/67638011