1

I'm doing a crackme to learn some reversing, and I stumbled upon this code generated by C++ MFC:

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

Before that code a comparison is done, such as cmp al, bl where al and bl hold some value read from the serial

The thing that confused me, is I figured that the cmp and two sbb instructions are equivalent to this pseudocode:

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

However this confused me because eax can never be 0, so the zero flag will always be set. Therefore, I figure the chunk of code

test eax, eax
jz exit

is useless because it does nothing- but how can this be? I don't think their C++ compiler would generate useless code like that

Where am I wrong here?

  • 1
    What is the code before first sbb? – Igor Skochinsky Jul 25 '16 at 7:39
  • the zero flag will always be clear, rather than set, but you are correct that the branch will never be taken. – peter ferrie Jul 29 '16 at 15:46
1

are you sure it was compiler generated ?
may be it was hand crafted or deliberately coded like wise may be it checks the sign flag further down in the jz path may be red herring ?

well whatever it requires more info based on the info provided only thing that pops up is a check for sign flag further down the path

here is a small compilable c code that shows what flags and results are for the operations in the query

#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;
}

result

:\>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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.