使用add添加空寄存器?

时间:2017-10-22 01:04:40

标签: assembly x86-64

我正在查看看起来像这样的汇编代码:

addl   %eax, -8(%rbp)

我知道寄存器%eax中有一个值,但在此行之前尚未触及-8(%rbp)。我是否认为它是空的,只会将%eax + 0的值放入-8(%rbp)?

2 个答案:

答案 0 :(得分: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()的返回值未知)。

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

文件 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()的返回值是什么,值 0 是否设置为<指向的内存区域强> -4(%rbp),然后再添加 1

答案 1 :(得分:2)

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

我确信在这种情况下,如果那是有效的代码,那么在该指令之前的某个时刻rbp是用一个合理的值写的。根据您如何拆卸或查看此信息,您可能会将某些数据模式作为代码进行反汇编。由于x86很难无法正确拆解,所以如果这是分解代码,你必须假设某些百分比可能是错误的。如果这只是来自编译器的直接汇编或手工编写,那么假设它不是错误的代码那么你只是在代码中没有足够的回溯或者在此之前调用以查看正在写入的寄存器。

注意一个寄存器不能是空的&#34;这些位将具有一个状态,并且对于位存储,不存在空状态,只有零或一个。