缺少堆栈更新

Alb*_*chi 5 c stack pointers

我试图深入研究堆栈分配,所以我打算获得这样的堆栈配置:

0x000009 -> 0,
0x000005 -> 1,
0x000001 -> 2,
...
Run Code Online (Sandbox Code Playgroud)

这是代码:

int main(){

    int i;
    int j;
    int pseudoarray;

    printf("address of i \t\t%p\n",&i);
    printf("address of j \t\t%p\n",&j);
    printf("address of pseudoarray \t%p\n\n",&pseudoarray);

    for(i =0;i<10;i++){

        *((&pseudoarray)-i)=i;
        printf("Written at \t%p value \t%d\n\n",(&pseudoarray)-i, i);

        for(j =0; j<10;j++){
            printf("Read at \t%p value \t%d\n",(&pseudoarray-j), *((&pseudoarray-j)));
        }
        printf("\n\n\n");
    }

    printf("\n%d times done",i);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,它只写入第三个单元,然后不写入任何内容。

这是它打印的内容(从第6次写入操作到10的打印与5相同):

C:\Users\Halib\OneDrive\Documents\Corsi\Corso C>plain.exe
address of i            0061FF1C
address of j            0061FF18
address of pseudoarray  0061FF14

Written at      0061FF14 value  0

Read at         0061FF14 value  0         <-- wrote a 0 here
Read at         0061FF10 value  4200912
Read at         0061FF0C value  4201019
Read at         0061FF08 value  4201019
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263



Written at      0061FF10 value  1

Read at         0061FF14 value  0
Read at         0061FF10 value  1         <-- wrote a 1 here
Read at         0061FF0C value  4201019
Read at         0061FF08 value  4201019
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263



Written at      0061FF0C value  2

Read at         0061FF14 value  0
Read at         0061FF10 value  1
Read at         0061FF0C value  2
Read at         0061FF08 value  2
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263



Written at      0061FF08 value  3

Read at         0061FF14 value  0
Read at         0061FF10 value  1
Read at         0061FF0C value  2
Read at         0061FF08 value  2          <-- I expected 3 here
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263



Written at      0061FF04 value  4

Read at         0061FF14 value  0
Read at         0061FF10 value  1
Read at         0061FF0C value  2
Read at         0061FF08 value  2
Read at         0061FF04 value  6422280    <-- expected 4 here
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263



Written at      0061FF00 value  5

Read at         0061FF14 value  0
Read at         0061FF10 value  1
Read at         0061FF0C value  2
Read at         0061FF08 value  2
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214946
Read at         0061FEFC value  4199673
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  157728263
Run Code Online (Sandbox Code Playgroud)

编辑:

代码修改:尝试:

int i;
int j;
int pseudoarray;

printf("address of i \t\t%p\n",&i);
printf("address of j \t\t%p\n",&j);
printf("address of pseudoarray \t%p\n\n",&pseudoarray);


for(i =0;i<10;i++){

    *((&pseudoarray)+i)=i;
}

    printf("\n\n");

for(j =0; j<10;j++){
        printf("Read at \t%p value \t%d\n",(&pseudoarray+j), *((&pseudoarray+j)));
    }

return 0;
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

address of i            0061FF1C
address of j            0061FF18
address of pseudoarray  0061FF14



Read at         0061FF14 value  0
Read at         0061FF10 value  1
Read at         0061FF0C value  2
Read at         0061FF08 value  2
Read at         0061FF04 value  6422280
Read at         0061FF00 value  4214921
Read at         0061FEFC value  4199645
Read at         0061FEF8 value  6422312
Read at         0061FEF4 value  -2
Read at         0061FEF0 value  -498040528
Run Code Online (Sandbox Code Playgroud)

有人可以帮我吗?非常感谢。

mev*_*ets 7

编写工作尚未停止,但是您打印值的方式正在破坏它们。假定您的堆栈指针通常位于0061FF08。当您在内部循环中调用printf()时,它将发出类似于以下内容的代码:

...
      push  %r0   / assume it computed *(&pseudoarray-j) int r0
      push  %r1   /  assume it computed &pseudoarray-1 into r1
      push  %r3   /  fmt string
      call  printf
      add   $12, %sp
 ....
Run Code Online (Sandbox Code Playgroud)

因此,这几乎覆盖了您的某些伪数组[-j]条目,因为几乎所有堆栈都向下生长。由于ABI偏爱某些堆栈对齐方式,这使情况变得复杂,因此您可以花几句话就摆脱它,但是一旦转义就可以完成。

如果要引起一些真正的混乱,请不要从伪数组中减去,而是添加到其中,这样您将覆盖所使用函数的调用帧的位。顺便说一下,这就是缓冲区溢出和类似机制劫持程序的方式。ps:当编译器为程序分配堆栈空间时,通常会在顶部附近发出如下序列:

func:
    push  %frame     / save the frame pointer register
    mov   %sp, %frame  / save the stack end pointer.
    sub   $num, %sp    / this allocates space for local vars.
Run Code Online (Sandbox Code Playgroud)

并返回:

mov  %frame, %sp
pop  %frame
ret
Run Code Online (Sandbox Code Playgroud)

因此在函数的代码生成部分,它可以自由发出如下序列:

push   %r0
call   tolower
add    $4, %sp
Run Code Online (Sandbox Code Playgroud)

修改堆栈,并允许lower构造自己的堆栈框架。当前堆栈指针下方的堆栈内存可能暂时可用,但是很难将其与编译器同步。如果您想尝试一下:

void play() {
   int    save[10];
   int    i;
   int    temp;
   for (i = 0; i < 10; i++) {
         (&temp)[-i] = 1 << i;
   }
   for (i = 0; i < 10; i++) {
          save[i] = (&temp)[-i];
   }
   for (i = 0; i < 10; i++) {
          printf("%d vs %d\n", save[i], (&temp)[-i]);
   }
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 这实际上不是C。#UB人看到这些时会眨眨眼,喷出胡言乱语。
  2. 在一定程度上,这将不会产生一致的结果,并且是编程的一种不好方法,它们是正确的。
  3. 这是发现,这是对编译器的有效使用。
  4. 您可能必须使用-O0,-std = c90之类的字词仔细调整编译器选项,以使其表现出来。