我是汇编语言的初学者,并注意到编译器发出的x86代码通常在释放/优化模式下保持帧指针,当它可以使用EBP寄存器时.
我理解为什么帧指针可能使代码更容易调试,并且如果alloca()在函数内调用则可能是必要的.但是,x86只有很少的寄存器,并使用其中两个寄存器来保存堆栈帧的位置,当一个就足够了,对我来说没有意义.为什么即使在优化/发布版本中省略框架指针也是一个坏主意?
考虑以下简单程序:
int main(int argc, char **argv)
{
char buffer[256];
buffer[0] = 0x41;
buffer[128] = 0x41;
buffer[255] = 0x41;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在x86-64机器上使用GCC 4.7.0编译.用GDB反汇编main()给出:
0x00000000004004cc <+0>: push rbp
0x00000000004004cd <+1>: mov rbp,rsp
0x00000000004004d0 <+4>: sub rsp,0x98
0x00000000004004d7 <+11>: mov DWORD PTR [rbp-0x104],edi
0x00000000004004dd <+17>: mov QWORD PTR [rbp-0x110],rsi
0x00000000004004e4 <+24>: mov BYTE PTR [rbp-0x100],0x41
0x00000000004004eb <+31>: mov BYTE PTR [rbp-0x80],0x41
0x00000000004004ef <+35>: mov BYTE PTR [rbp-0x1],0x41
0x00000000004004f3 <+39>: mov eax,0x0
0x00000000004004f8 <+44>: leave
0x00000000004004f9 <+45>: ret
Run Code Online (Sandbox Code Playgroud)
当缓冲区为256字节时,为什么sub rsp只有0x98 = 152d?当我将数据移入缓冲区[0]时,它似乎只是使用分配的堆栈帧之外的数据并使用rbp来引用,那么甚至sub rsp的点是什么,0x98? …
我很难在汇编级别调试程序,因为 GDB 正在跳过代码的某些部分。代码是:
#include <stdio.h>
#define BUF_SIZE 8
void getInput(){
char buf[BUF_SIZE];
gets(buf);
puts(buf);
}
int main(int argc, char* argv){
printf("Digite alguma coisa, tamanho do buffer eh: %d\n", BUF_SIZE);
getInput();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该程序是用gcc -ggdb -fno-stack-protector -mpreferred-stack-boundary=4 -o exploit1 exploit1.c
在 gdb中编译的,我添加了break getInput,当我运行disas getInput它时返回我:
Dump of assembler code for function getInput:
0x00000000004005cc <+0>: push %rbp
0x00000000004005cd <+1>: mov %rsp,%rbp
0x00000000004005d0 <+4>: sub $0x10,%rsp
0x00000000004005d4 <+8>: lea -0x10(%rbp),%rax
0x00000000004005d8 <+12>: mov %rax,%rdi
0x00000000004005db <+15>: mov $0x0,%eax …Run Code Online (Sandbox Code Playgroud) 我遇到了一个问题,即在添加断点时 gdb 将行号映射到错误的内存地址。
以下 x86 Linux 汇编程序打印“hello”。
/* hello.s */
.section .data
str:
.ascii "hello\n"
strlen = . - str
.section .text
print:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl $4, %eax
movl $1, %ebx
movl $str, %ecx
movl $strlen, %edx
int $0x80
popl %ebx
movl %ebp, %esp
popl %ebp
ret
.globl _start
_start:
call print
movl $1, %eax
movl $0, %ebx
int $0x80
Run Code Online (Sandbox Code Playgroud)
我用调试信息编译它,然后链接。
$ as -g --32 -o hello.o hello.s
$ ld -m elf_i386 -o hello hello.o …Run Code Online (Sandbox Code Playgroud)