2017-09-21 135 views
-1
obj.CurrSize -= size; 
0x00000000003ad2d7 <+183>: mov eax,0x0  
0x00000000003ad2dc <+188>: test rax,rax 
0x00000000003ad2df <+191>: je 0x3ad2e6 <+198> 
0x00000000003ad2e1 <+193>: call 0x0 
0x00000000003ad2e6 <+198>: mov rax, 0xffffffffffffff60 
0x00000000003ad2ed <+205>: sub rbx,r15 
0x00000000003ad2f0 <+208>: add QWORD PTR fs:[rax],rbx` 

为什么要测试零,然后如果为零,跳过一条指令,但其他人也一样?这个asm代码是什么意思?

+0

尝试移除该位,看看它是否有所作为。 –

+0

@MadPhysicist? – vladon

+0

@PeterCordes它与-O2一起叮当响。看,有eax归零,但rax测试。 – vladon

回答

2

读一个无关的问题,exposes a pattern that looked similar to yours,我想我找到了你的奇怪代码的由来。

最大的可能是这个代码来自线程相关的C++ 11功能的扩展,在使用__gthread_active_p()检查,如果pthread库中居然挂特别的东西。

是有可能

大多数代码应对线程的libstdC++的问题(但如果不需要线程支持合理的回退)充斥着

if(__gthread_active_p()) 

这又通常归结为检查是否符号__pthread_key_create是定义为不同于NULL的内容。这里的诀窍是,这样一个函数是,它被声明为__attribute__ ((weak)),所以,如果没有提供定义(即如果pthread库未链接),而不是抱怨,链接器只是解析其对NULL的引用。

所以,你在代码中看到的是编译器留下来做线程相关的东西(比如获取一个保护一些共享资源的互斥锁)的检查。预连接代码可能是这样的:

mov eax,__pthread_key_create 
    test rax,rax 
    jz .skip_mutex_init 
    call __pthread_init_some_mutex 
.skip_mutex_init: 
    mov rax, 0xffffffffffffff60 
    sub rbx,r15 
    add QWORD PTR fs:[rax],rbx` 

在那里你看到决心NULL指针所有__pthread符号。当然,最终的代码是非常愚蠢的 - 编译器不知道链接器是否将被调用-lpthread,并且链接器只是执行愚蠢的替换 - 再次运行优化器太晚了(除非启用了LTO,但这是一个完全不同的游戏)。

您可以看到自己类似的图案playing with the compiler explorer:尝试启用/禁用链接完整的二进制文件(右边的按钮和11010标题),并在命令行上添加/删除-pthread。现在

,我没能精确再现你的结果,但可能是来自不同版本的libstdc++被使用,或者在你的代码中使用了不同的线程感知组件(我只是尝试用std::mutexstd::shared_ptr) 。

+0

不,调用0x0 '只是调用下一条指令,而不是空指针。这是已经静态链接的程序(gdb disasm的输出)的一个失败。 – vladon

+0

我不确定,IIRC通常会将gdb转储为'call 0x3ad2e6 <+0>',类似于上面的相对跳转。不过,如果像你说的那样,它看起来像手写代码来阻止反编译器等等 - 在函数内部插入虚假调用本身会破坏启发式规则以重建函数入口点/块。 –

+0

哦,废话,是的,这是一个NULL指针加载,而不是'mov eax,imm32'。我只是不习惯GDB版本的Intel语法。 'objdump'将会打印出'DWORD PTR:0'。 (@vladon) –