加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

以前的堆栈变量

发布时间:2020-12-16 06:59:45 所属栏目:百科 来源:网络整理
导读:我有这个问题,我递归调用C中的函数,C是词法范围的,所以我只能访问当前的堆栈帧.我想从前一个函数调用中创建的前一个堆栈帧中提取参数和局部变量,同时我在当前堆栈帧上 我知道前一个递归调用的值仍然在堆栈上,但我无法访问这些值,因为它们被“隐藏”在活动堆
我有这个问题,我递归调用C中的函数,C是词法范围的,所以我只能访问当前的堆栈帧.我想从前一个函数调用中创建的前一个堆栈帧中提取参数和局部变量,同时我在当前堆栈帧上

我知道前一个递归调用的值仍然在堆栈上,但我无法访问这些值,因为它们被“隐藏”在活动堆栈帧下?

我想从前一个堆栈中提取参数和局部变量,并将它们复制到copy_of_buried_arg和copy_of_buried_loc;

需要使用GAS来提取变量的内联汇编,这是我到目前为止所做的,而且我整天都在尝试,我似乎无法弄明白,我把纸叠在纸上并进行了计算,但没有什么是工作,我也尝试删除对printf的调用,所以堆栈将更清洁,但我不能找出正确的算法.这是到目前为止的代码,我的函数在第二次迭代时停止

#include <stdio.h>

char glo = 97;   // just for fun 97 is ascii lowercase 'a'
int copy_of_buried_arg;
char copy_of_buried_loc;

void rec(int arg) {
  char loc;

  loc = glo + arg * 2; // just for fun,some char arithmetic
  printf("inside rec() arg=%d loc='%c'n",arg,loc);

  if (arg != 0) {
    // after this assembly code runs,the copy_of_buried_arg and
    // copy_of_buried_loc variables will have arg,loc values from
    // the frame of the previous call to rec().
    __asm__("n
            movl 28(%esp),%eax #moving stack pointer to old ebp (pointing it to old ebp)n
            addl $8,%eax       #now eax points to the first argument for the old ebp n
            movl (%eax),%ecx   #copy the value inside eax to ecxn 
            movl %ecx,copy_of_buried_arg   # copies the old argumentn
    n

");

    printf("copy_of_buried_arg=%u copy_of_buried_loc='%c'n",copy_of_buried_arg,copy_of_buried_loc);
  } else {
      printf("there is no buried stack framen");// runs if argument = 0 so only the first time
  }

  if (arg < 10) {
    rec(arg + 1);
  }
}

int main (int argc,char **argv) {
  rec(0);

  return 0;
}

解决方法

我可以尝试提供帮助,但在GAS中没有Linux或程序集.但计算应该类似:

这是几次通话后的筹码.典型的堆栈帧设置创建堆栈帧的链接列表,其中EBP是当前堆栈帧并指向其先前堆栈帧的旧值.

+-------+
ESP-> |loc='c'|     <- ESP currently points here.
      +-------+
EBP-> |oldEBP |--+  <- rec(0)'s call frame
      +-------+  |
      |retaddr|  |  <- return value of rec(1)
      +-------+  |
      |arg=1  |  |  <- pushed argument of rec(1)
      +-------+  |
      |loc='a'|  |  <- local variable of rec(0)
      +-------+  |
   +--|oldEBP |<-+  <- main's call frame
   |  +-------+
   |  |retaddr|     <- return value of rec(0)
   |  +-------+ 
   |  |arg=0  |     <- pushed argument of rec(0)
   |  +-------+
  |/ 
to main's call frame

这是由以下顺序创建的:

>首先推送参数arg.
>调用该函数,按下返回地址.
>推出即将成为旧的EBP,保留先前的堆栈帧.
>将ESP(堆栈顶部,包含oldEBP)移动到EBP中,创建新的堆栈帧.
>减去局部变量的空间.

这对32位堆栈有影响,EBP 8将始终是调用的第一个参数,EBP 12是第二个参数,等等.EBP-n始终是局部变量的偏移量.

然后获取前一个loc和arg的代码(在MASM中):

mov ecx,[ebp]              // get previous stack frame
mov edx,[ecx]+8            // get first argument
mov copy_of_buried_arg,edx // save it
mov dl,[ecx]-1             // get first char-sized local variable.
mov copy_of_buried_loc,dl  // save it

或者我对GAS的最好猜测(我不知道但是知道它向MASM倒退):

movl (%ebp),ecx
movl 8(%ecx),edx
movl edx,copy_of_buried_arg
movb -1(%ecx),dl
movb dl,copy_of_buried_loc

在Windows上使用VS2010使用MASM输出代码:

inside rec() arg=0 loc='a'
there is no buried stack frame
inside rec() arg=1 loc='c'
copy_of_buried_arg=0 copy_of_buried_loc='a'
inside rec() arg=2 loc='e'
copy_of_buried_arg=1 copy_of_buried_loc='c'
inside rec() arg=3 loc='g'
copy_of_buried_arg=2 copy_of_buried_loc='e'
inside rec() arg=4 loc='i'
copy_of_buried_arg=3 copy_of_buried_loc='g'
inside rec() arg=5 loc='k'
copy_of_buried_arg=4 copy_of_buried_loc='i'
inside rec() arg=6 loc='m'
copy_of_buried_arg=5 copy_of_buried_loc='k'
inside rec() arg=7 loc='o'
copy_of_buried_arg=6 copy_of_buried_loc='m'
inside rec() arg=8 loc='q'
copy_of_buried_arg=7 copy_of_buried_loc='o'
inside rec() arg=9 loc='s'
copy_of_buried_arg=8 copy_of_buried_loc='q'
inside rec() arg=10 loc='u'
copy_of_buried_arg=9 copy_of_buried_loc='s'

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读