user-0 提问: 如何使用内嵌汇编获得斐波那契数列

回复:
user: user-1
content: #include <stdio.h> #include <stdlib.h>  //int fib(int n){ //  if(n==0) return 0; //  if(n==1) return 1; //  return fib(n-2)+fib(n-1); //}  int main(int argc, char *argv[]) {     int n, r=0;     if (argc < 2) {         printf("Usage: %s number(<40)\n", argv[0]);         return -1;     }     n = atoi(argv[1]); //  r=fib(n);     __asm {      // FILL YOUR CODE HERE     // evaluate r = f(n)  //r=fib(n);            mov         ecx,n            push        ecx            call        fib            add         esp,4            mov         r,eax            jmp         lbEnd fib://int fib(int n){            push        ebp            mov         ebp,esp            sub         esp,0x40            push        ebx            push        esi            push        edi //        if(n==0) return 0;            cmp         dword ptr [ebp+8],0            jne         step2            xor         eax,eax            jmp         endfunc //        if(n==1) return 1; step2:     cmp         dword ptr [ebp+8],1            jne         step3            mov         eax,1            jmp         endfunc //        return fib(n-2)+fib(n-1); step3:     mov         eax,dword ptr [ebp+8]            sub         eax,2            push        eax            call        fib            add         esp,4            mov         esi,eax            mov         ecx,dword ptr [ebp+8]            sub         ecx,1            push        ecx            call        fib            add         esp,4            add         eax,esi //    } endfunc:   pop         edi            pop         esi            pop         ebx            mov         esp,ebp            pop         ebp            ret lbEnd:     }     printf("fib(%d) = %d\n", n, r);     return 0; }

user: user-1
content: VC调试时按Alt+8打开汇编窗口看每句C对应的汇编。

user: user-1
content: #include <stdio.h> #include <stdlib.h>  int fib(int n){     if(n==0) return 0;     if(n==1) return 1;     return fib(n-2)+fib(n-1); }  int main(int argc, char *argv[]) {     int n, r=0;     if (argc < 2) {         printf("Usage: %s number(<40)\n", argv[0]);         return -1;     }     n = atoi(argv[1]);     r=fib(n);     __asm {      // FILL YOUR CODE HERE     // evaluate r = f(n)         nop     }     printf("fib(%d) = %d\n", n, r);     return 0; } 1:    #include <stdio.h> 2:    #include <stdlib.h> 3: 4:    int fib(int n){ 00401020   push        ebp 00401021   mov         ebp,esp 00401023   sub         esp,40h 00401026   push        ebx 00401027   push        esi 00401028   push        edi 5:        if(n==0) return 0; 00401029   cmp         dword ptr [ebp+8],0 0040102D   jne         fib+13h (00401033) 0040102F   xor         eax,eax 00401031   jmp         fib+42h (00401062) 6:        if(n==1) return 1; 00401033   cmp         dword ptr [ebp+8],1 00401037   jne         fib+20h (00401040) 00401039   mov         eax,1 0040103E   jmp         fib+42h (00401062) 7:        return fib(n-2)+fib(n-1); 00401040   mov         eax,dword ptr [ebp+8] 00401043   sub         eax,2 00401046   push        eax 00401047   call        @ILT+5(fib) (0040100a) 0040104C   add         esp,4 0040104F   mov         esi,eax 00401051   mov         ecx,dword ptr [ebp+8] 00401054   sub         ecx,1 00401057   push        ecx 00401058   call        @ILT+5(fib) (0040100a) 0040105D   add         esp,4 00401060   add         eax,esi 8:    } 00401062   pop         edi 00401063   pop         esi 00401064   pop         ebx 00401065   mov         esp,ebp 00401067   pop         ebp 00401068   ret 9: 10:   int main(int argc, char *argv[]) 11:   { 00401080   push        ebp 00401081   mov         ebp,esp 00401083   sub         esp,48h 00401086   push        ebx 00401087   push        esi 00401088   push        edi 12:       int n, r=0; 00401089   mov         dword ptr [ebp-8],0 13:       if (argc < 2) { 00401090   cmp         dword ptr [ebp+8],2 00401094   jge         main+2Fh (004010af) 14:           printf("Usage: %s number(<40)\n", argv[0]); 00401096   mov         eax,dword ptr [ebp+0Ch] 00401099   mov         ecx,dword ptr [eax] 0040109B   push        ecx 0040109C   push        offset string "Usage: %s number(<40)\n" (0041302c) 004010A1   call        dword ptr [__imp__printf (004150a8)] 004010A7   add         esp,8 15:           return -1; 004010AA   or          eax,0FFh 004010AD   jmp         main+6Ah (004010ea) 16:       } 17:       n = atoi(argv[1]); 004010AF   mov         edx,dword ptr [ebp+0Ch] 004010B2   mov         eax,dword ptr [edx+4] 004010B5   push        eax 004010B6   call        dword ptr [__imp__atoi (004150a4)] 004010BC   add         esp,4 004010BF   mov         dword ptr [ebp-4],eax 18:       r=fib(n); 004010C2   mov         ecx,dword ptr [ebp-4] 004010C5   push        ecx 004010C6   call        @ILT+5(fib) (0040100a) 004010CB   add         esp,4 004010CE   mov         dword ptr [ebp-8],eax 19:       __asm { 20: 21:       // FILL YOUR CODE HERE 22:       // evaluate r = f(n) 23:           nop 004010D1   nop 24:       } 25:       printf("fib(%d) = %d\n", n, r); 004010D2   mov         edx,dword ptr [ebp-8] 004010D5   push        edx 004010D6   mov         eax,dword ptr [ebp-4] 004010D9   push        eax 004010DA   push        offset string "fib(%d) = %d\n" (0041301c) 004010DF   call        dword ptr [__imp__printf (004150a8)] 004010E5   add         esp,0Ch 26:       return 0; 004010E8   xor         eax,eax 27:   } 004010EA   pop         edi 004010EB   pop         esi 004010EC   pop         ebx 004010ED   mov         esp,ebp 004010EF   pop         ebp 004010F0   ret

user: user-2
content: 啊，这两条：     jge __start     jmp __exit 可以改成：     jl __exit  思维短路了。

user: user-2
content: 这个很容易用非递归实现：  int fib(int n) {   __asm{     //push ebx  //     //push esi  // not necessary for cl and icl compilers     mov ecx,n     mov eax,0     mov ebx,1     mov edx,3     cmp ecx,eax     jle __exit     inc eax     cmp ecx,edx     jge __start     jmp __exit   __start:     cmp edx,ecx     jg __done     mov esi,eax     mov eax,ebx     add esi,ebx     inc edx     mov ebx,esi     jmp __start   __done:     mov eax,esi   __exit:     //pop esi     //pop ebx   } }

user: user-0
content: 引用 2 楼 user-4 的回复:很明显你这个是递归，递归很深，栈空间溢出了请问下怎么解决呢？我不太会用汇编

user: user-0
content: 我不太会用汇编 应该怎么使用呢？上面的汇编代码是我根据C反汇编写上去的

user: user-3
content: fib是个函数, 没看到ret在那里

user: user-4
content: 很明显你这个是递归，递归很深，栈空间溢出了

user: user-0
content: 我用的VS反汇编 再放到__asm里面 就不行呢