我在理解这个汇编代码的作用时遇到了一些麻烦。该函数接受一个整数参数,我应该弄清楚哪些参数允许我在这个块的末尾进行跳转。但是,我完全迷失在cmpsb
正在做的事情上。我不知道%es
和%ds
是什么或正在比较什么(参数和0x8048bb0作为字符串?)。
lea 0x1e(%esp),%edi //loads the integer argument into edi register
mov $0x8048bb0,%esi //moves 0x8048bb0 into esi register
mov $0xd,%ecx //moves 13 into ecx register
repz cmpsb %es:(%edi),%ds:(%esi) //a loop and a string byte comparison?
seta %dl //sets dl if previous comparison results in >
setb %al //sets al if previous comparison results in <
cmp %al,%dl //compares al and dl
je 8048851 <phase_3_of_5+0x69> //jumps if al and dl are equal (meaning the above comparison was equal)
我已经尝试过搜索cmpsb
的工作原理,但我找不到任何像这样的内容。
此外,seta
和setb
有什么意义?如果它只是检查cmpsb
是否相等,为什么je
之后才会出现这种情况呢?
答案 0 :(得分:1)
lea 0x1e(%esp),%edi //loads a pointer to a string from stack to EDI
mov $0x8048bb0,%esi //loads a pointer to another string to ESI
mov $0xd,%ecx //moves 13 into ECX register
repz cmpsb %es:(%edi),%ds:(%esi) //loops comparing values in ES:EDI and DS:ESI, continues until ECX is zero or a mismatching byte is found
seta %dl //sets DL if previous comparison results in >
setb %al //sets AL if previous comparison results in <
cmp %al,%dl //compares AL and DL
je 8048851 <phase_3_of_5+0x69> //jumps if AL and DL are equal (meaning the above comparison was equal)
ES
和DS
是段寄存器,:
将段寄存器与偏移量分开。在16位世界中,它们很容易使用:地址DS:SI
是DS * 16 + SI。在32/64位分段世界中,它们更复杂,它们是指向段表的指针,物理地址是从那里派生的。要理解的要点是,您总是需要一个段和一个偏移寄存器来指向任何东西。段寄存器可能在汇编代码中隐藏,但它始终存在。
段寄存器还表示即使ESI
等于EDI
,但您使用DS:ESI
和ES:EDI
,它们也可能指向不同的内存位置。当然,DS:ESI
和ES:ESI
可以指向不同的位置。
代码不比较字符串和整数。 ESI
和EDI
都包含整数值,但它们用作指向内存位置的指针,并使用CMPSB
命令将这些位置中的字节相互比较。 REPZ
一直持续到比较不为零,或ECX
变为零。
SETA
/ SETB
指令非常无用,除非稍后使用它们的值。代码可以检查是否设置了零标志,这意味着所有比较都是相同的。因此ES:EDI
和DS:ESI
指向的所有13个字节都是相等的。
代码不设置方向标志,因此不清楚要比较的字节是从ES:EDI
开始还是向后。逻辑上的事情就是前进。