2017-10-22 114 views
1

我看汇编代码看起来像这样:使用添加一个空的注册?

addl %eax, -8(%rbp) 

我知道寄存器%eax中有一个值,但-8(%RBP)尚未到这条线之前感动。我是否认为它是空的,并且会将%eax + 0的值放入-8(%rbp)?

+2

不可以,以前肯定是指定的,你需要看起来更难。它可能是用不同的指针写的,例如相对于'rsp'。请注意,内存通常不会被清零,特别是不会经常指向“rbp”的堆栈。 – Jester

回答

4

正如@Jester在评论中指出的,它应该在该行之前的某个位置有一个指定的值,否则您正在查看潜在的未定义行为。

让我们考虑下面的C源代码和相应的组件输出(编译GCC,不优化):

文件add_1_noinit.c

int main(void) { 
     int a; 

     return a += 1; 
} 

文件add_1_noinit.s (GCC -O0 -S add_1_noinit.c):

... snip ... 
.LFB0: 
     .cfi_startproc 
     pushq %rbp 
     .cfi_def_cfa_offset 16 
     .cfi_offset 6, -16 
     movq %rsp, %rbp 
     .cfi_def_cfa_register 6 
     addl $1, -4(%rbp) 
     movl -4(%rbp), %eax 
     popq %rbp 
     .cfi_def_cfa 7, 8 
     ret 
     .cfi_endproc 
.LFE0: 
... snip ... 

正如你所看到的,add_1_noinit.c不会初始化变量a,导致未定义的行为(返回值main()未知)。

现在让我们看一个初始化一个变量的输出:

文件add_1_init.c

int main(void) { 
     int a = 0; 

     return a += 1; 
} 

文件add_1_init.s(GCC -O0 -S add_1_init。 c):

... snip ... 
.LFB0: 
     .cfi_startproc 
     pushq %rbp 
     .cfi_def_cfa_offset 16 
     .cfi_offset 6, -16 
     movq %rsp, %rbp 
     .cfi_def_cfa_register 6 
     movl $0, -4(%rbp) 
     addl $1, -4(%rbp) 
     movl -4(%rbp), %eax 
     popq %rbp 
     .cfi_def_cfa 7, 8 
     ret 
     .cfi_endproc 
.LFE0: 
... snip ... 

正如你所看到的,在这个例子,我们知道什么是的main()的返回值,并将其值是增加到之前设置为由-4(%RBP)所指向的内存区域。

+0

所以-​​8(%rbp)在该行之前没有提及,也没有使用%rsp的任何引用,但是存在一个存储在-24(%rbp)的数组指针。 -8(%rbp)会​​在该数组中存储第5个元素吗?我不认为这是正确的,因为我认为指针会指向数组的其他位置。我完全丧失了。 – wenjay

2

通常在硅存储位中只有两个状态0和1,所以即使你没有看到设置该寄存器的代码,它不是“空的”,它包含一个模式,指令将使用该模式,崩溃或正确执行。现在在模拟逻辑中,你可以有三个或更多的状态位为0,1,x,其中用x表示的任何东西都是x或者任何用x表示的x都是。在这种情况下,你可以有一个“空”或至少未初始化的寄存器。 Xes就像他们感染你的模拟的瘟疫一样,最终把整个事情变成xes。所以你必须非常小心,在阅读之前总是写。包括寄存器。

我相信在这种情况下,如果这是有效的代码,那么在该指令之前的某个点rbp被写入一个理智的值。取决于你如何分解这个或者看着它,它可能是你已经反编译为代码的一些数据模式。作为x86很难正确反汇编,所以如果这是组装代码,你必须假定一些百分比可能是错误的。如果这只是从编译器直接汇编或手工编写的,那么假设它不是错误的代码,那么在代码或调用前面看到正在写入的寄存器就不够用了。

注意一个寄存器不能为空,这些位将会有一个状态,而位存储不是空状态,只是零或一个。