C程序将测试两个字符串是否匹配,并且每次都会打印一条消息。
这是反向代码段的样子:
call strcmp //compares the strings
test eax,eax
jne 1706
如果ZF = 0,我知道jne将会跳转。
/>我不明白这条线是怎么回事:
test eax,eax
是什么引起了这条线?
它与strcmp有什么关系?
我知道,如果测试结果不为零,则ZF = 0,因此jne将会跳转。
它到底有什么比较?它与strcmp有什么关系?
#1 楼
调用之后,寄存器eax
将包含来自strcmp
的返回码。 test eax, eax
与and eax, eax
(按位and
)相同,只是它不将结果存储在eax
中。因此,eax
不受此测试的影响,但例如,零标记是必需的。为使
test eax, eax
首先工作,必须使用jne
。 jne
与jnz
相同,就像je
与jz
一样。两者均基于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
表示发生了错误。
评论
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?