这条 sbb 指令的结果是什么?

逆向工程 x86 快手
2021-06-23 23:59:07

我正在做一个crackme来学习一些逆向,我偶然发现了这个由C++ MFC生成的代码:

sbb eax, eax
sbb eax, -1
test eax, eax
jz exit

在该代码之前进行比较,例如cmp al, blal 和 bl 保存从串行读取的某些值

让我感到困惑的是,我认为 cmp 和两个 sbb 指令等效于以下伪代码:

cmp a,b
eax=-1 if b>a
eax=1 otherwise

然而这让我感到困惑,因为 eax 永远不可能为 0,所以零标志将始终被设置。因此,我认为代码块

test eax, eax
jz exit

没用,因为它什么都不做——但这怎么可能呢?我不认为他们的 C++ 编译器会生成那样无用的代码

我哪里错了?

1个回答

你确定它是编译器生成的吗?
可能是手工制作或故意编码的明智之举可能是检查jz路径中进一步向下的标志标志可能是红鲱鱼?

好吧,无论它需要更多基于信息的信息,提供的唯一信息是检查路径下方的标志标志

这是一个小的可编译的 c 代码,显示查询中的操作的标志和结果

#include <stdio.h>
int helper (unsigned char a , unsigned char b )
{
    unsigned char res = 0;
    unsigned char flag = 0;
    __asm
    {
        xor eax,eax
        xor ecx,ecx
        mov al,a        ;          = 0  1  2  3  4  5  6  7
        mov cl,b        ;          = 4  4  4  4  4  4  4  4
        cmp al,cl       ;cf        = 1  1  1  1  0  0  0  0
        sbb eax,eax     ;x-x-cf    =-1 -1 -1 -1  0  0  0  0
        sbb eax,-1      ;x-(-1)-cf =-1 -1 -1 -1  1  1  1  1
        mov res,al      ;          = ---------""-----------
        pushfd
        xor eax,eax
        mov eax,dword ptr ss:[esp]
        popfd
        lahf
        mov flag , al
    }
    bool zf = ((flag & 64)==64);
    bool sf = ((flag & 128)==128);
    bool cf = ((flag & 1)==1);
    printf("%2x %2x %2x %2x %2x %2x\n" ,a,b,res,zf,sf,cf);
}
int main (void)
{
    printf(" a  b  r  z  s  c\n");
    for (unsigned char i = 0; i < 8 ;i++){
        helper(i,4);
    }
    return 0;
}

结果

:\>dir /b & cl /nologo runasm.cpp & runasm.exe
runasm.cpp
runasm.cpp
 a  b  r  z  s  c
 0  4 ff  0  1  1
 1  4 ff  0  1  1
 2  4 ff  0  1  1
 3  4 ff  0  1  1
 4  4  1  0  0  1
 5  4  1  0  0  1
 6  4  1  0  0  1
 7  4  1  0  0  1