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

C程序将测试两个字符串是否匹配,并且每次都会打印一条消息。

这是反向代码段的样子:

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


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

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

test eax,eax


是什么引起了这条线?
它与strcmp有什么关系?

我知道,如果测试结果不为零,则ZF = 0,因此jne将会跳转。
它到底有什么比较?它与strcmp有什么关系?

评论

EAX是IA32调用约定用来将整数值或内存地址返回到调用例程的寄存器。根据设计,strcpy可以在EAX中返回-1,0或1,其中0表示两个字符串都匹配。 TEST EAX,EAX测试EAX是否为零,并设置或取消设置ZF位。

strcpy在EAX中返回一个整数,而不是在FLAGS中返回一个整数。看看`testl` eax对抗eax吗?有关此指令如何根据EAX设置标志的信息。

等效于cmp eax,0:使用CMP reg,0和OR reg,reg测试寄存器是否为零?和`testl` eax对抗eax?

#1 楼

调用之后,寄存器eax将包含来自strcmp的返回码。 test eax, eaxand eax, eax(按位and)相同,只是它不将结果存储在eax中。因此,eax不受此测试的影响,但例如,零标记是必需的。

为使test eax, eax首先工作,必须使用jnejnejnz相同,就像jejz一样。两者均基于ZF(零标记)值起作用。

如果ZF = 0,则将采用jne分支,因此,每当strcmp返回非零值(即字符串不相等)时,将执行eax分支。相反,如果从strcmp返回时jne包含零,则不会发生通过q4312079q的跳转。

评论


strcmp比较字符串,如果字符串相等,则将eax设置为零

–乔什
'18 Sep 3'在10:49

我的意思是,它执行逻辑AND。但是它到底能检查什么呢? jne怎么会不开火?要让jne不跳,eax的值应该是多少?

–user1584421
'18 Sep 3'在10:55

jne跳跃和不跳跃的条件是什么?为了跳跃/不跳跃,eax必须是什么?以及这与strcmp有什么关系?

–user1584421
18/09/3在11:20

@ user1584421请稍等一下,然后将您已经知道的内容放在一起。 eax包含strcmp的返回值。测试就像按位测试,只不过它只设置标志。将值与自身相加会得到相同的值,因此测试eax时,eax会根据包含的eax设置标志。当运算结果为零时设置ZF。未设置ZF时,jne会跳转。因此,当strcmp返回非零值时将执行跳转,这意味着字符串不相等。

–霍布斯
18-09-3在16:42



#2 楼

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

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

#3 楼

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


测试eax,eax会执行二进制和两个输入
,要使其跳跃的eax需要为0
如果eax为0,则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");
    }

}


主拆卸


#4 楼

基本上,与此汇编代码关联的原始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用于存储函数的返回码,测试test eax, eax通常用于在调用后检查此返回码(通常是是相反的,而eax == 0表示发生了错误。