美文网首页计算机系统基础
Experiment of basic computer sys

Experiment of basic computer sys

作者: 桐桑入梦 | 来源:发表于2019-05-30 12:36 被阅读0次

    Today,we will do a experiment about computer system basic knowledge.The experiment is based on Ubuntu system.Before we start our experiment,we should install Ubuntu System.

    Step 1:

    write program

    #include<stdio.h>
    int main(void)
    {
            float x=-0.125;
            float y=7.5;
            int z=100;
            printf("x=%f y=%f z=%d\n",x,y,z);
            return 0;
    }
    

    Step 2:

    compile and run programs
    input command:gcc -g -p.c -o p
    generate executable file p

    Step 3:

    view these variables of numbers of machine in the memory.
    use command x/nfu<addr>view the memory
    Parameter n,which indicates the number of memory unite to view
    Parameter f is t,indicating that variables are displayed in binary format
    Parameter u is b,indicating that the length of each address unite is one byte


    #include<stdio.h>
    int main(void)
    {
            int x=-32768;
            short y=522;
            unsigned z=65530;
            char c='@';
            float a=-1.1;
            double b=10.5;
    
            return 0;
    }
    
    
    

    https://blog.csdn.net/u011068702/article/details/53925415
    https://blog.csdn.net/maikeerdai/article/details/17530937


    使用命令

    gcc -S prog1.c
    

    然后prog1.s





    使用命令

    gcc -c prog1.c
    

    生成文件prog1.o
    使用命令

    gcc -o prog prog1.c
    

    生成可以执行文件prog


    下面查看两个文件的不同:
    https://blog.csdn.net/zoomdy/article/details/50563680
    使用命令

    objdump -d prog1.o
    

    查看prog1.o反汇编之后的源码




    使用命令

    objdump -d prog
    

    查看prog1反汇编之后的源码







    下面要开始认真的做了,嘻嘻嘻


    冲鸭

    bomb.c源码

    /***************************************************************************
     * Dr. Evil's Insidious Bomb, Version 1.1
     * Copyright 2011, Dr. Evil Incorporated. All rights reserved.
     *
     * LICENSE:
     *
     * Dr. Evil Incorporated (the PERPETRATOR) hereby grants you (the
     * VICTIM) explicit permission to use this bomb (the BOMB).  This is a
     * time limited license, which expires on the death of the VICTIM.
     * The PERPETRATOR takes no responsibility for damage, frustration,
     * insanity, bug-eyes, carpal-tunnel syndrome, loss of sleep, or other
     * harm to the VICTIM.  Unless the PERPETRATOR wants to take credit,
     * that is.  The VICTIM may not distribute this bomb source code to
     * any enemies of the PERPETRATOR.  No VICTIM may debug,
     * reverse-engineer, run "strings" on, decompile, decrypt, or use any
     * other technique to gain knowledge of and defuse the BOMB.  BOMB
     * proof clothing may not be worn when handling this program.  The
     * PERPETRATOR will not apologize for the PERPETRATOR's poor sense of
     * humor.  This license is null and void where the BOMB is prohibited
     * by law.
     ***************************************************************************/
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "support.h"
    #include "phases.h"
    
    /* 
     * Note to self: Remember to erase this file so my victims will have no
     * idea what is going on, and so they will all blow up in a
     * spectaculary fiendish explosion. -- Dr. Evil 
     */
    
    FILE *infile;
    
    int main(int argc, char *argv[])
    {
        char *input;
    
        /* Note to self: remember to port this bomb to Windows and put a 
         * fantastic GUI on it. */
    
        /* When run with no arguments, the bomb reads its input lines 
         * from standard input. */
        if (argc == 1) {  
        infile = stdin;
        } 
    
        /* When run with one argument <file>, the bomb reads from <file> 
         * until EOF, and then switches to standard input. Thus, as you 
         * defuse each phase, you can add its defusing string to <file> and
         * avoid having to retype it. */
        else if (argc == 2) {
        if (!(infile = fopen(argv[1], "r"))) {
            printf("%s: Error: Couldn't open %s\n", argv[0], argv[1]);
            exit(8);
        }
        }
    
        /* You can't call the bomb with more than 1 command line argument. */
        else {
        printf("Usage: %s [<input_file>]\n", argv[0]);
        exit(8);
        }
    
        /* Do all sorts of secret stuff that makes the bomb harder to defuse. */
        initialize_bomb();
    
        printf("Welcome to my fiendish little bomb. You have 6 phases with\n");
        printf("which to blow yourself up. Have a nice day!\n");
    
        /* Hmm...  Six phases must be more secure than one phase! */
        input = read_line();             /* Get input                   */
        phase_1(input);                  /* Run the phase               */
        phase_defused();                 /* Drat!  They figured it out!
                          * Let me know how they did it. */
        printf("Phase 1 defused. How about the next one?\n");
    
        /* The second phase is harder.  No one will ever figure out
         * how to defuse this... */
        input = read_line();
        phase_2(input);
        phase_defused();
        printf("That's number 2.  Keep going!\n");
    
        /* I guess this is too easy so far.  Some more complex code will
         * confuse people. */
        input = read_line();
        phase_3(input);
        phase_defused();
        printf("Halfway there!\n");
    
        /* Oh yeah?  Well, how good is your math?  Try on this saucy problem! */
        input = read_line();
        phase_4(input);
        phase_defused();
        printf("So you got that one.  Try this one.\n");
        
        /* Round and 'round in memory we go, where we stop, the bomb blows! */
        input = read_line();
        phase_5(input);
        phase_defused();
        printf("Good work!  On to the next...\n");
    
        /* This phase will never be used, since no one will get past the
         * earlier ones.  But just in case, make this one extra hard. */
        input = read_line();
        phase_6(input);
        phase_defused();
    
        /* Wow, they got it!  But isn't something... missing?  Perhaps
         * something they overlooked?  Mua ha ha ha ha! */
        
        return 0;
    }
    
    

    看看汇编是啥东西呢?


    phase_1
    0000000000400ee0 <phase_1>:      #函数的名称和函数的起始地址,可见函数最终变成了一些列的指令,没有其他的东西
      400ee0:       48 83 ec 08             sub    $0x8,%rsp  #R[rsp] <- R[rsp]-8 栈指针寄存器往下移动8个字节          
      400ee4:       be 00 24 40 00          mov    $0x402400,%esi  #R[esi] <- 402400 
      400ee9:       e8 4a 04 00 00          callq  401338 <strings_not_equal> #调用函数,同时把函数的返回地址400eee写入到M[R[rsp]],即M[R[rsp]] <- 400eee
      400eee:       85 c0                   test   %eax,%eax #test测试指令,若EAX是0,则ZF=1,否则ZF=0  eg.test指令对两个操作数进行与与运算,但是不改变操作数的数值
      400ef0:       74 05                   je     400ef7 <phase_1+0x17> #je = jz ,ZF=1时候执行
      400ef2:       e8 43 05 00 00          callq  40143a <explode_bomb> #调用函数,同时把函数的返回地址写入M[R[rsp]],覆盖调用函数<string_not_equal>的返回地址,即M[R[rsp]]<-400ef7
      400ef7:       48 83 c4 08             add    $0x8,%rsp # R[rsp]  <- R[rsp]+8
      400efb:       c3                      retq   #R[rsp]<-R[rsp]-8 , R[rcs]<-M[R[rsp]] 取出返回地址,并且把返回地址写入RCS寄存器中
    
    <string_length>
    000000000040131b <string_length>:
      40131b:       80 3f 00                cmpb   $0x0,(%rdi)  #判断给出的首地址的第一个单元的内容是否为0,如果是0,那么直接跳转到401332,把0放入RAX,然后返回
      40131e:       74 12                   je     401332 <string_length+0x17>
      401320:       48 89 fa                mov    %rdi,%rdx #使用RDX保存字符串的首地址
      401323:       48 83 c2 01             adda    $0x1,%rdx #在循环中,RDX不断加一
      401327:       89 d0                   mov    %edx,%eax #R[eax]<-R[edx]
      401329:       29 f8                   sub    %edi,%eax #R[eax]<-R[eax]-R[edi]
      40132b:       80 3a 00                cmpb   $0x0,(%rdx) #M[R[rdx]]中的内容和0做比较
      40132e:       75 f3                   jne    401323 <string_length+0x8> #如果M[R[rdx]]中内容不是0,那么继续循环执行,即判断是否到达字符串的结尾
      401330:       f3 c3                   repz retq #
      401332:       b8 00 00 00 00          mov    $0x0,%eax #R[rax]<-0
      401337:       c3                      retq #返回
    
    
    string_not_equal
    0000000000401338 <strings_not_equal>:
      401338:       41 54                   push   %r12      #R[rsp]<-R[rsp]-8 , M[R[rsp]]<-R[r12]
      40133a:       55                      push   %rbp      #R[rsp]<-R[rsp]-8,M[R[rsp]]<-R[rbp]
      40133b:       53                      push   %rbx      #R[rsp]<-R[rsp]-8,M[R[rsp]]<-R[rbx]
      40133c:       48 89 fb                mov    %rdi,%rbx #R[rbx]<-R[rdi]  使用rbx接受第一个参数,
      40133f:       48 89 f5                mov    %rsi,%rbp #R[rbp]<-R[rsi]
      401342:       e8 d4 ff ff ff          callq  40131b <string_length> #计算参数RDI表示的字符串的长度
      401347:       41 89 c4                mov    %eax,%r12d #R[12d]保存字符串的长度
      40134a:       48 89 ef                mov    %rbp,%rdi  #R[rdi]<-R[rbp],此时RDI中的值为0x402400  
      40134d:       e8 c9 ff ff ff          callq  40131b <string_length> #计算字符串的长度,具体的字符串的内容可以查看内存中的数据
      401352:       ba 01 00 00 00          mov    $0x1,%edx  #R[edx]<-1
      401357:       41 39 c4                cmp    %eax,%r12d #比较两个字符串的长度
      40135a:       75 3f                   jne    40139b <strings_not_equal+0x63> #如果两个字符串的长度不相同,那么返回1
      40135c:       0f b6 03                movzbl (%rbx),%eax  #R[eax]<-M[R[rbx]] 这个过程经过0扩展,RBX保存输入的字符串的首地址,所以此时EAX保存第一个字符的数值
      40135f:       84 c0                   test   %al,%al #判断这个字符的低8位是否是0
      401361:       74 25                   je     401388 <strings_not_equal+0x50> #如果是0,即ZF=1跳转,然后返回0,但是如果第一个字符的数值为0,那么长度也是0
      401363:       3a 45 00                cmp    0x0(%rbp),%al #比较RBP这个地址表示的字符串的第一个字符和输入的字符串的第一个
      401366:       74 0a                   je     401372 <strings_not_equal+0x3a> #如果两个字符相同,跳转
      401368:       eb 25                   jmp    40138f <strings_not_equal+0x57> #如果不相同,返回1
      40136a:       3a 45 00                cmp    0x0(%rbp),%al
      40136d:       0f 1f 00                nopl   (%rax)
      401370:       75 24                   jne    401396 <strings_not_equal+0x5e>
      401372:       48 83 c3 01             add    $0x1,%rbx #R[rbx]<-R[rbx]+1
      401376:       48 83 c5 01             add    $0x1,%rbp #R[rbp]<-R[rbp]+1
      40137a:       0f b6 03                movzbl (%rbx),%eax #把M[R[rbx]]内容放到EAX中,即输入的第二个字符
      40137d:       84 c0                   test   %al,%al #如果是空字符,ZF=1
      40137f:       75 e9                   jne    40136a <strings_not_equal+0x32> #如果不是空字符,继续判断
      401381:       ba 00 00 00 00          mov    $0x0,%edx #如果两个字符串全部相同,返回0
      401386:       eb 13                   jmp    40139b <strings_not_equal+0x63>
      401388:       ba 00 00 00 00          mov    $0x0,%edx #
      40138d:       eb 0c                   jmp    40139b <strings_not_equal+0x63>
      40138f:       ba 01 00 00 00          mov    $0x1,%edx
      401394:       eb 05                   jmp    40139b <strings_not_equal+0x63>
      401396:       ba 01 00 00 00          mov    $0x1,%edx
      40139b:       89 d0                   mov    %edx,%eax
      40139d:       5b                      pop    %rbx #恢复
      40139e:       5d                      pop    %rbp #恢复
      40139f:       41 5c                   pop    %r12 #恢复
      4013a1:       c3                      retq #返回
    

    具体的分析过程
    <phase_1>在ESI中保存了数据0x402400然后调用函数<strings_not_equal>,然后判断EAX寄存器是否为0.如果为0,那么ZF=1,此时会执行je指令,跳过explode_bomb函数.因此需要EAX为0即可.那么什么时候EAX为0呢?看一下<string_not_equal>函数,发现这个函数使用了一个循环比较ESI和EDI表示的两个字符串,如果相同,返回0,如果不同,返回1。因此,只要输入的字符串满足和程序给出的字符串相同即可。

    RAX保存输入的字符串的地址 在调用函数<phase_1>之前,使用RDI保存RAX的值,即第一个参数是输入的字符串的地址
    进入函数<phase_1>中时,没有修改RDI的值(RDI仍然是字符串的首地址),同时设置RSI的值,两个寄存器作为两个<string_not_equal>的参数,这两个参数表示两个字符串 把输入的字符串的地址保存的寄存器RBX中
    查看内容从地址0x402400开始的字符串,长度为52

    使用十六进制显示一下,方便阅读


    使用十六进制显示的字符串

    这个字符串的长度为54


    保存到文件文件
    使用C语言读入这段16进制的数,用字符输出
    结果:
    Border relations with Canada have never been better.
    

    把这个字符串输入,结果如下图所示:


    第一个炸弹拆开的截图

    第二个炸弹:


    <phase_2>
    0000000000400efc <phase_2>:
      400efc:       55                      push   %rbp
      400efd:       53                      push   %rbx
      400efe:       48 83 ec 28             sub    $0x28,%rsp #R[rsp]<-R[rsp]-28
      400f02:       48 89 e6                mov    %rsp,%rsi #R[rsi]<-R[rsp] ,设置第二个参数
      400f05:       e8 52 05 00 00          callq  40145c <read_six_numbers>
      400f0a:       83 3c 24 01             cmpl   $0x1,(%rsp) #比较M[R[rsp]]和1
      400f0e:       74 20                   je     400f30 <phase_2+0x34> #如果M[R[rsp]]=1
      400f10:       e8 25 05 00 00          callq  40143a <explode_bomb> #如果不是1,那么爆炸了
      400f15:       eb 19                   jmp    400f30 <phase_2+0x34> #无条件跳转到0x400f30
      400f17:       8b 43 fc                mov    -0x4(%rbx),%eax #R[eax]<-M[R[rbx]-4]
      400f1a:       01 c0                   add    %eax,%eax #R[eax]<-R[eax]+R[eax]
      400f1c:       39 03                   cmp    %eax,(%rbx) #比较EAX和M[R[rbx]]
      400f1e:       74 05                   je     400f25 <phase_2+0x29> #如果相同,跳转一下,如果不同,爆炸了
      400f20:       e8 15 05 00 00          callq  40143a <explode_bomb>
      400f25:       48 83 c3 04             add    $0x4,%rbx #R[rbx]<-R[rbx]+0x4
      400f29:       48 39 eb                cmp    %rbp,%rbx #比较RBP和RBX
      400f2c:       75 e9                   jne    400f17 <phase_2+0x1b> #如果不相同,那么循环
      400f2e:       eb 0c                   jmp    400f3c <phase_2+0x40> #如果相同,那么可以成功的拆除炸弹了
      400f30:       48 8d 5c 24 04          lea    0x4(%rsp),%rbx #R[rbx]<-R[rsp]+0x4
      400f35:       48 8d 6c 24 18          lea    0x18(%rsp),%rbp #R[rbp]<-R[rsp]+0x18
      400f3a:       eb db                   jmp    400f17 <phase_2+0x1b>
      400f3c:       48 83 c4 28             add    $0x28,%rsp
      400f40:       5b                      pop    %rbx
      400f41:       5d                      pop    %rbp
      400f42:       c3                      retq
    
    
    画一下对应的栈结构,发现<phase_2>通过不断的移动RBX进行相邻值之间的比较,当RBP=RBX时候停止比较 <read_six_numbers>
    000000000040145c <read_six_numbers>:
      40145c:       48 83 ec 18             sub    $0x18,%rsp #R[rsp]<-R[rsp]-0x18
      401460:       48 89 f2                mov    %rsi,%rdx #R[rdx]<-R[rsi],R[rsi]保存<phase_2>函数的栈底的地址,从这个地址开始依次存数6个,每个数占4个字节,此时RDX是第一个数的地址
      401463:       48 8d 4e 04             lea    0x4(%rsi),%rcx #R[rcx]<-R[rsi]+0x4 第二个数的地址
      401467:       48 8d 46 14             lea    0x14(%rsi),%rax#R[rax]<-R[rsi]+0x14 最后一个数的地址
      40146b:       48 89 44 24 08          mov    %rax,0x8(%rsp) #M[R[rsp]+8]<-R[rax]
      401470:       48 8d 46 10             lea    0x10(%rsi),%rax #R[rax]<-R[rsi]+16
      401474:       48 89 04 24             mov    %rax,(%rsp) #M[R[rsp]]<-R[rax]
      401478:       4c 8d 4e 0c             lea    0xc(%rsi),%r9 #R[r9]<-R[rsi]+12
      40147c:       4c 8d 46 08             lea    0x8(%rsi),%r8 #R[r8]<-[R[rsi]+8
      401480:       be c3 25 40 00          mov    $0x4025c3,%esi #R[esi]<-0x4025c3
      401485:       b8 00 00 00 00          mov    $0x0,%eax #R[eax]<-0
      40148a:       e8 61 f7 ff ff          callq  400bf0 <__isoc99_sscanf@plt>
      40148f:       83 f8 05                cmp    $0x5,%eax #比较一下
      401492:       7f 05                   jg     401499 <read_six_numbers+0x3d>
      401494:       e8 a1 ff ff ff          callq  40143a <explode_bomb>
      401499:       48 83 c4 18             add    $0x18,%rsp
      40149d:       c3                      retq
    
    

    第三个炸弹:


    <phase_3>
    0000000000400f43 <phase_3>:
      400f43:       48 83 ec 18             sub    $0x18,%rsp #R[rsp]<-R[rsp]-24
      400f47:       48 8d 4c 24 0c          lea    0xc(%rsp),%rcx #R[rcx]<-R[rsp]+12
      400f4c:       48 8d 54 24 08          lea    0x8(%rsp),%rdx #R[rdx]<-R[rsp]+8
      400f51:       be cf 25 40 00          mov    $0x4025cf,%esi #R[esi]<-$0x4025cf
      400f56:       b8 00 00 00 00          mov    $0x0,%eax #R[eax]<-$0x0
      400f5b:       e8 90 fc ff ff          callq  400bf0 <__isoc99_sscanf@plt> #调用输入的函数
      400f60:       83 f8 01                cmp    $0x1,%eax #EAX和$0x1比较
      400f63:       7f 05                   jg     400f6a <phase_3+0x27> #如果EAX>1,那么跳转到0x400f6a
      400f65:       e8 d0 04 00 00          callq  40143a <explode_bomb> #如果小于等于,那么爆炸,说明EAX需要大于1,说明至少输入两个数
      400f6a:       83 7c 24 08 07          cmpl   $0x7,0x8(%rsp) #比较M[R[rsp]+8]和7
      400f6f:       77 3c                   ja     400fad <phase_3+0x6a> #如果M[R[rsp]+8]>7,那么爆炸,说明M[R[rsp]+8]<=7
      400f71:       8b 44 24 08             mov    0x8(%rsp),%eax #R[eax]<-M[R[rsp]+8]
      400f75:       ff 24 c5 70 24 40 00    jmpq   *0x402470(,%rax,8) #这是一个间接跳转的指令,地址=*(0x402470+RAX*8)
      400f7c:       b8 cf 00 00 00          mov    $0xcf,%eax
      400f81:       eb 3b                   jmp    400fbe <phase_3+0x7b>
      400f83:       b8 c3 02 00 00          mov    $0x2c3,%eax
      400f88:       eb 34                   jmp    400fbe <phase_3+0x7b>
      400f8a:       b8 00 01 00 00          mov    $0x100,%eax
      400f8f:       eb 2d                   jmp    400fbe <phase_3+0x7b>
      400f91:       b8 85 01 00 00          mov    $0x185,%eax
      400f96:       eb 26                   jmp    400fbe <phase_3+0x7b>
      400f98:       b8 ce 00 00 00          mov    $0xce,%eax
      400f9d:       eb 1f                   jmp    400fbe <phase_3+0x7b>
      400f9f:       b8 aa 02 00 00          mov    $0x2aa,%eax
      400fa4:       eb 18                   jmp    400fbe <phase_3+0x7b>
      400fa6:       b8 47 01 00 00          mov    $0x147,%eax
      400fab:       eb 11                   jmp    400fbe <phase_3+0x7b>
      400fad:       e8 88 04 00 00          callq  40143a <explode_bomb>
      400fb2:       b8 00 00 00 00          mov    $0x0,%eax
      400fb7:       eb 05                   jmp    400fbe <phase_3+0x7b>
      400fb9:       b8 37 01 00 00          mov    $0x137,%eax
      400fbe:       3b 44 24 0c             cmp    0xc(%rsp),%eax #比较 EAX 和 M[R[rsp]+12]
      400fc2:       74 05                   je     400fc9 <phase_3+0x86> #如果相等,那么成功拆掉炸弹,否则继续执行(继续执行会爆炸)
      400fc4:       e8 71 04 00 00          callq  40143a <explode_bomb>
      400fc9:       48 83 c4 18             add    $0x18,%rsp #把栈增长的部分收回
      400fcd:       c3                      retq #返回
    
    函数在执行的过程中有一个间接跳转指令,跳转地址是M[0x402470+R[rax]*8 ] ,于是查看一下内存,发现根据第一个参数的不同(第一个参数需要小于等于7),对应的跳转的地址不同,因此只要确定第一个参数,然后根据跳转之后的指令可以确定第二个参数的值
    输入文件的内容 第三个炸弹拆除的截图 作业完成

    第四个炸弹:

    <phase_4>函数执行的流程:

    1. 读入两个参数,地址为RSP+8,RSP+12(RSP+0xc)
    2. 如果没有成功读取两个参数或者第一个参数大于0xe,那么爆炸,否则执行3
    3. 调用函数<func4>,如果函数返回值不是0,爆炸,否则执行4
    4. 判断给出的第二个参数是否是0,如果不是0则爆炸,如果是0,那么这个炸弹可以成功拆除.
    <phase_4>
    000000000040100c <phase_4>:
      40100c:       48 83 ec 18             sub    $0x18,%rsp
      401010:       48 8d 4c 24 0c          lea    0xc(%rsp),%rcx
      401015:       48 8d 54 24 08          lea    0x8(%rsp),%rdx
      40101a:       be cf 25 40 00          mov    $0x4025cf,%esi
      40101f:       b8 00 00 00 00          mov    $0x0,%eax
      401024:       e8 c7 fb ff ff          callq  400bf0 <__isoc99_sscanf@plt>
      401029:       83 f8 02                cmp    $0x2,%eax
      40102c:       75 07                   jne    401035 <phase_4+0x29>
      40102e:       83 7c 24 08 0e          cmpl   $0xe,0x8(%rsp)
      401033:       76 05                   jbe    40103a <phase_4+0x2e>
      401035:       e8 00 04 00 00          callq  40143a <explode_bomb>
      40103a:       ba 0e 00 00 00          mov    $0xe,%edx
      40103f:       be 00 00 00 00          mov    $0x0,%esi
      401044:       8b 7c 24 08             mov    0x8(%rsp),%edi
      401048:       e8 81 ff ff ff          callq  400fce <func4>
      40104d:       85 c0                   test   %eax,%eax
      40104f:       75 07                   jne    401058 <phase_4+0x4c>
      401051:       83 7c 24 0c 00          cmpl   $0x0,0xc(%rsp)
      401056:       74 05                   je     40105d <phase_4+0x51>
      401058:       e8 dd 03 00 00          callq  40143a <explode_bomb>
      40105d:       48 83 c4 18             add    $0x18,%rsp
      401061:       c3                      retq
    
    <func4>
    0000000000400fce <func4>:    
    初始值:ESI=0x0,EDX=0xe,EDI=第一个变量的地址
      400fce:       48 83 ec 08             sub    $0x8,%rsp 
      400fd2:       89 d0                   mov    %edx,%eax #R[eax]<-R[edx],即EAX=0xe
      400fd4:       29 f0                   sub    %esi,%eax #R[eax]<-R[eax]-R[esi],即EAX=0xe-0=0xe
      400fd6:       89 c1                   mov    %eax,%ecx #R[ecx]<-R[eax],即ECX=0xe 
      400fd8:       c1 e9 1f                shr    $0x1f,%ecx #R[ecx]<-R[ecx]>>1,逻辑右移,ECX=7
      400fdb:       01 c8                   add    %ecx,%eax #R[eax]<-R[eax]+R[ecx] EAX=22
      400fdd:       d1 f8                   sar    %eax #R[eax]<-R[eax]>>1 ,算术右移 EAX=11
      400fdf:       8d 0c 30                lea    (%rax,%rsi,1),%ecx #R[ecx]<-R[rax]+R[rsi]
      400fe2:       39 f9                   cmp    %edi,%ecx #比较EDI和ECX
      400fe4:       7e 0c                   jle    400ff2 <func4+0x24> #如果ECX小于等于EDI,跳转0x400ff2
      400fe6:       8d 51 ff                lea    -0x1(%rcx),%edx #R[edx]<-R[rcx]-1
      400fe9:       e8 e0 ff ff ff          callq  400fce <func4> #递归调用函数
      400fee:       01 c0                   add    %eax,%eax #R[eax]<-R[eax]+R[eax]
      400ff0:       eb 15                   jmp    401007 <func4+0x39> #跳转一下,然后回收增长的空间,之后返回上一层函数
      400ff2:       b8 00 00 00 00          mov    $0x0,%eax #R[eax]<-0
      400ff7:       39 f9                   cmp    %edi,%ecx #比较EDI和ECX
      400ff9:       7d 0c                   jge    401007 <func4+0x39> #如果ECX>=EDI,跳转到0x401007,直接函数递归结束,递归的终止条件
      400ffb:       8d 71 01                lea    0x1(%rcx),%esi #R[esi]<-R[rcx]+1
      400ffe:       e8 cb ff ff ff          callq  400fce <func4> #递归
      401003:       8d 44 00 01             lea    0x1(%rax,%rax,1),%eax #R[eax]<-R[rax]+R[rax]+1
      401007:       48 83 c4 08             add    $0x8,%rsp
      40100b:       c3                      retq
    

    https://blog.csdn.net/u011596455/article/details/60322568

    相关文章

      网友评论

        本文标题:Experiment of basic computer sys

        本文链接:https://www.haomeiwen.com/subject/qvpmtctx.html