Experiment of basic computer system

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容