在 strcmp 之后测试 eax,eax 的目的

逆向工程 拆卸 部件 C
2021-06-09 03:04:32

这是我试图逆转的第一个程序,也是我对该领域的介绍。

C 程序将测试两个字符串是否匹配,并且它会为每个场合 printf() 一条消息。

这是反向代码片段的样子:

call strcmp //compares the strings
test eax,eax
jne 1706

我知道 jne 会跳,如果 ZF=0。

我不明白的是这条线是怎么回事:

test eax,eax

是什么导致了这条线?它与 strcmp 有什么关系?

我知道如果test的结果不为零,ZF=0,所以jne会跳。但它究竟比较什么,它与 strcmp 有什么关系?

4个回答

调用后,注册eax将包含来自 的返回代码strcmpThetest eax, eaxand eax, eax(bitwise and)相同只是它不将结果存储在eax. 所以eax不受测试的影响,但零标志是,例如。

test eax, eaxjne首先完成工作所必需的jne是一样的jnz,就像je是一样的一样jz两者都基于 ZF(零标志)值进行操作。

如果ZF=0 并且因此每当返回非零值(即字符串不相等)时,采用jne分支相反,如果从 返回包含零不会发生跳转通路strcmpeaxstrcmpjne

您可能会错过call strcmp不会为您设置ZF的事实- 它会在 EAX 寄存器中返回结果。但是 JNE 指令测试ZF,并且测试 eax,eax用于根据 EAX 设置 ZF。(实际上,相反,EAX=1 -> ZF=0)。

我建议阅读一些关于 x86 汇编的简单书籍,它会对你有很大帮助。

strcmp() 的原型

int strcmp(
   const char *string1,
   const char *string2 
);

该函数返回一个 int ,其解释如下,
所以我认为这可以回答您的问题,即它何时跳转,何时不
跳转,如果 eax 是 > 或 < 0
,如果 eax == 0 则不跳转

Return Value
The return value for each of these functions indicates   
the lexicographic relation of string1 to string2.

< 0   string1 less than string2

  0   string1 identical to string2

> 0   string1 greater than string2

test eax,eax 执行一个二进制和两个输入,
并且它要跳转 eax 需要为 0 如果 eax 为 0 test eax,eax 会将 ZF 设置为 1 否则它会将 ZF 设置为 0
通常测试 eax 将被使用,如果高级语言的程序测试结果是这样的

if(!strcmp( a, b ) ) { do something } 

请参阅下面的示例程序和反汇编

>>> eax = -1
>>> print eax & eax
-1
>>> eax = 0
>>> print eax & eax
0
>>> eax = 1
>>> print eax & eax
1
>>>

示例程序

#include <stdio.h>
#include <string.h>

int main (void) {
    char *first="same";char *secon="same";char *third="diff";char *forth="tiff";
    int fis = strcmp(first,secon);
    int sec = strcmp(first,third);
    int tid = strcmp(first,forth);
    printf("%8x %8x %8x\n",fis,sec,tid);
    if(!strcmp(first,secon)){
        printf("trings are same \n");
    }
    if( strcmp(first,third) == 1 ) {
        printf("second string has a chareceter that is greater than first string\n");
    }
        if( strcmp(first,forth) == -1 ) {
        printf("second string has a chareceter that is lesser than first string\n");
    }

}

主要拆解 在此处输入图片说明

基本上,与此汇编代码关联的原始 C 代码将是:

if (strcmp (str1, str2)) // call strcmp and do the 'test eax, eax'
  goto error; // str1 != str2 --> jne 1706

// str1 == str2
// Do legitimate code

error:
  // Do what you need to handle the error

如果您想要一种记住什么的方法,test eax, eax可以在 C 中像这样翻译它:

bool test = (eax == 0)

注意eax用于存储函数的返回码,testtest eax, eax经常用于在调用后检查这个返回码(通常,这是相反的,eax == 0意味着发生了错误)。