Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用C代码和汇编代码帮助绘制堆栈_C_Assembly_Stack_X86 - Fatal编程技术网

使用C代码和汇编代码帮助绘制堆栈

使用C代码和汇编代码帮助绘制堆栈,c,assembly,stack,x86,C,Assembly,Stack,X86,我试图画一个堆栈,就像它在secondCall函数的“returncount”行之前出现的那样。我试图绘制它,以便它能够显示三个活动函数main、firstCall和secondCall的所有三个帧(或激活记录) 有人能帮我完成堆栈图吗? 我试图在调用下一个函数之前,绘制基本(ebp)和堆栈(esp)指针在每个堆栈帧中的位置 C代码如下: #include <stdio.h> #include <stdlib.h> #include <unistd.h>

我试图画一个堆栈,就像它在secondCall函数的“returncount”行之前出现的那样。我试图绘制它,以便它能够显示三个活动函数main、firstCall和secondCall的所有三个帧(或激活记录)

有人能帮我完成堆栈图吗? 我试图在调用下一个函数之前,绘制基本(ebp)和堆栈(esp)指针在每个堆栈帧中的位置

C代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


int secondCall(int a, int b) {
  int count;
  count = write(STDOUT_FILENO, &"hello\n", 6);
  count += write(STDOUT_FILENO, &"jbnd007\n", 8);
  count += a + b;
  return count;
}
int firstCall(void) {
  int local;
  local = secondCall(4, 2);
  return local;
}
int main(int argc, char** argv) {
  int result;
  result = firstCall();
  return (EXIT_SUCCESS);
}
    .file   "A3Program2.c"
    .section    .rodata
.LC0:
    .string "hello\n"
.LC1:
    .string "jbnd007\n"
    .text
.globl secondCall
    .type   secondCall, @function
secondCall:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $40, %esp
    movl    $6, 8(%esp)
    movl    $.LC0, 4(%esp)
    movl    $1, (%esp)
    call    write
    movl    %eax, -12(%ebp)
    movl    $8, 8(%esp)
    movl    $.LC1, 4(%esp)
    movl    $1, (%esp)
    call    write
    addl    %eax, -12(%ebp)
    movl    12(%ebp), %eax
    movl    8(%ebp), %edx
    leal    (%edx,%eax), %eax
    addl    %eax, -12(%ebp)
    movl    -12(%ebp), %eax
    leave
    ret
    .size   secondCall, .-secondCall
.globl firstCall
    .type   firstCall, @function
firstCall:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $40, %esp
    movl    $2, 4(%esp)
    movl    $4, (%esp)
    call    secondCall
    movl    %eax, -12(%ebp)
    movl    -12(%ebp), %eax
    leave
    ret
    .size   firstCall, .-firstCall
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    call    firstCall
    movl    %eax, 12(%esp)
    movl    $0, %eax
    leave
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
    .section    .note.GNU-stack,"",@progbits
我现在的堆栈图是:

+------------------------------+ high address
| original position of stack pointer
+------------------------------+
| saved value of ebp <- ebp (base pointer when in main)
+------------------------------+
| alignment spacing (don’t really know how big until runtime)
+------------------------------+
|
+------------------------------+
|
+------------------------------+
|
+------------------------------+
...
Each line represents 4 bytes (from lowest address (left) to highest address (right)).
+-----------------------------------+高位地址
|堆栈指针的原始位置
+------------------------------+

|ebp的保存值在
gdb
中的
return count
行中断,然后使用
x/30xw$esp
之类的方法打印堆栈。在输入要记录的堆栈部分之前,您可以提前中断并记下
$esp
,以获得比我胡乱猜测的30个单词更精确的计数。

我不打算为您做全部事情,但这里有一个关于如何完成所发生事情的详细解释

进入
main
时,堆栈如下所示:

    : (whatever)                        :
    +-----------------------------------+
    | return address (in main's caller) | <- %esp
    +-----------------------------------+
call    firstCall

    : (whatever)                        :
    +-----------------------------------+
    | return address (in main's caller) |
    +-----------------------------------+
    | saved %ebp                        | <- %ebp
    +-----------------------------------+
    : some unknown amount of space      :
    : (0, 4, 8 or 12 bytes)             :
    +-----------------------------------+
    | 16 bytes of reserved space        |
    |                                   |
    |                                   |
    |                                   |
    +-----------------------------------+
    | return address (in main)          | <- %esp
    +-----------------------------------+
…这就是你要做的。继续:

这将从堆栈指针中减去16个字节,这将创建16个字节的保留空间供
main
使用:

subl    $16, %esp

    : (whatever)                        :
    +-----------------------------------+
    | return address (in main's caller) |
    +-----------------------------------+
    | saved %ebp                        | <- %ebp
    +-----------------------------------+
    : some unknown amount of space      :
    : (0, 4, 8 or 12 bytes)             :
    +-----------------------------------+
    | 16 bytes of reserved  space       |
    |                                   |
    |                                   |
    |                                   | <- %esp
    +-----------------------------------+
由于
firstCall
末尾的
ret
指令,返回到
main
时,返回地址将再次弹出

……等等。只要按照
%esp
正在做的事情,以相同的方式跟踪代码即可

另一件可能需要解释的事情是出现在 各种例程的尾声代码。以下是
main
的工作原理:

就在
离开
靠近
main
末尾之前,堆栈看起来是这样的(我们从
firstCall
并在保留空间中存储一个值):

最后,
ret
弹出返回地址并在内部继续执行
无论什么叫
main

,这都是一个开始;你为什么停在那里?问题是什么?我不确定下一步要做什么
gdb
是一个在Linux下运行的调试程序。请提供终端会话记录。似乎是对你如何解决这个问题的一个完整的解释。兄弟,你是一个传奇!剩下的我来做!
subl    $16, %esp

    : (whatever)                        :
    +-----------------------------------+
    | return address (in main's caller) |
    +-----------------------------------+
    | saved %ebp                        | <- %ebp
    +-----------------------------------+
    : some unknown amount of space      :
    : (0, 4, 8 or 12 bytes)             :
    +-----------------------------------+
    | 16 bytes of reserved  space       |
    |                                   |
    |                                   |
    |                                   | <- %esp
    +-----------------------------------+
call    firstCall

    : (whatever)                        :
    +-----------------------------------+
    | return address (in main's caller) |
    +-----------------------------------+
    | saved %ebp                        | <- %ebp
    +-----------------------------------+
    : some unknown amount of space      :
    : (0, 4, 8 or 12 bytes)             :
    +-----------------------------------+
    | 16 bytes of reserved space        |
    |                                   |
    |                                   |
    |                                   |
    +-----------------------------------+
    | return address (in main)          | <- %esp
    +-----------------------------------+
    : (whatever)                        :
    +-----------------------------------+
    | return address (to main's caller) |
    +-----------------------------------+
    | saved %ebp                        | <- %ebp
    +-----------------------------------+
    : some unknown amount of space      :
    : (0, 4, 8 or 12 bytes)             :
    +-----------------------------------+
    | %eax returned by firstCall        |
    | (and 12 bytes that were never     |
    |  used)                            |
    |                                   | <- %esp
    +-----------------------------------+
movl   %ebp, %esp   ; (first part of "leave")

    : (whatever)                        :
    +-----------------------------------+
    | return address (in main's caller) |
    +-----------------------------------+
    | saved %ebp                        | <- %esp = current %ebp
    +-----------------------------------+ 
    : some unknown amount of space      :  }
    : (0, 4, 8 or 12 bytes)             :  }
    +-----------------------------------+  } all of this stuff is
    | %eax returned by firstCall        |  }  irrelevant now
    | (and 12 bytes that were never     |  }
    |  used)                            |  }
    |                                   |  }
    +-----------------------------------+

popl   %ebp         ; (second part of "leave")

    : (whatever)                        :
    +-----------------------------------+
    | return address (in main's caller) | <- %esp  (%ebp has now been restored to the
    +-----------------------------------+            value it had on entry to "main")
      (and now-irrelevant stuff below)