◆◆◆精通汇编的老大请入,请教几个内嵌汇编的问题◆◆◆

crossbow 2004-08-13 03:02:31
这几个函数都来自于VCL。

*********
* 问题1 *
*********

function CompareStr(const S1, S2: string): Integer; assembler;
asm
PUSH ESI
PUSH EDI

MOV ESI,EAX
MOV EDI,EDX

OR EAX,EAX
JE @@1
MOV EAX,[EAX-4]

@@1: OR EDX,EDX
JE @@2
MOV EDX,[EDX-4]

@@2: MOV ECX,EAX
CMP ECX,EDX
JBE @@3
MOV ECX,EDX

@@3: CMP ECX,ECX //是否是为了对齐?
REPE CMPSB
JE @@4
MOVZX EAX,BYTE PTR [ESI-1]
MOVZX EDX,BYTE PTR [EDI-1]

@@4: SUB EAX,EDX

POP EDI
POP ESI
end;

///////////////////////////////////////////////////////////////

function CompareText(const S1, S2: string): Integer; assembler;
asm
PUSH ESI
PUSH EDI
PUSH EBX

MOV ESI,EAX
MOV EDI,EDX

OR EAX,EAX
JE @@0
MOV EAX,[EAX-4]

@@0: OR EDX,EDX
JE @@1
MOV EDX,[EDX-4]

@@1: MOV ECX,EAX
CMP ECX,EDX
JBE @@2
MOV ECX,EDX

@@2: CMP ECX,ECX //是否是为了对齐?
@@3: REPE CMPSB
JE @@6

MOV BL,BYTE PTR [ESI-1]
CMP BL,'a'
JB @@4
CMP BL,'z'
JA @@4
SUB BL,20H

@@4: MOV BH,BYTE PTR [EDI-1]
CMP BH,'a'
JB @@5
CMP BH,'z'
JA @@5
SUB BH,20H

@@5: CMP BL,BH
JE @@3

MOVZX EAX,BL
MOVZX EDX,BH

@@6: SUB EAX,EDX

POP EBX
POP EDI
POP ESI
end;

请问上面两个函数中的 CMP ECX, ECX存在的目的是否都是为了对齐?我把他们注释掉也可以正常运行。

我查到数据是:

CMP Clocks Size
Operands 808x 286 386 486 Bytes
reg,reg 3 2 2 1 2
mem,reg 9+EA 7 5 2 2-4 (W88=13+EA)
reg,mem 9+EA 6 6 2 2-4 (W88=13+EA)
reg,immed 4 3 2 1 3-4
mem,immed 10+EA 6 5 2 3-6 (W88=14+EA)
accum,immed 4 3 2 1 2-3

如果是,请问为什么用CMP,好处是什么?

*********
* 问题2 *
*********

function StrLen(const Str: PChar): Cardinal; assembler;
asm
MOV EDX,EDI
MOV EDI,EAX

MOV ECX,0FFFFFFFFH //ECX = -1
XOR AL,AL //AL = 0
REPNE SCASB //把AL的内容与EDI作比较, 为0则字符串终止
MOV EAX,0FFFFFFFEH //EAX = -1
SUB EAX,ECX // -1 - ECX,返回值为负吗?

MOV EDI,EDX
end;

难道返回值为负数吗?

*********
* 问题3 *
*********

function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
asm
PUSH ESI
PUSH EDI

MOV ESI,P1
MOV EDI,P2

MOV EDX,ECX

XOR EAX,EAX //清0

AND EDX,3 //???

SHR ECX,1 //循环计数除以4
SHR ECX,1

REPE CMPSD //循环比较双字
JNE @@2 //不等于则返回False

MOV ECX,EDX //等于则继续

REPE CMPSB //循环比较单字
JNE @@2 //不等于则返回False

@@1: INC EAX //都等于返回True

@@2: POP EDI
POP ESI
end;

问题:AND EDX,3 有什么作用?取 EDX mod 4吗?

请得道高人赐教,谢谢。
...全文
485 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
crossbow 2004-08-18
  • 打赏
  • 举报
回复
请ehom老大接分:

http://community.csdn.net/Expert/topic/3284/3284781.xml?temp=.2817499
CDSoftwareWj 2004-08-17
  • 打赏
  • 举报
回复
学习
dicke 2004-08-17
  • 打赏
  • 举报
回复
学习中
WuChenCan 2004-08-17
  • 打赏
  • 举报
回复
高人啊!学习!
crossbow 2004-08-17
  • 打赏
  • 举报
回复
感谢
crossbow 2004-08-17
  • 打赏
  • 举报
回复
我已全部明白了,感谢ehom老大,技术扎实,语言简练。

感谢列位老大捧场帮助,谢谢!明天结贴加送分!
crossbow 2004-08-16
  • 打赏
  • 举报
回复
感谢 ehom 老大的指点,其它的都差不多弄清楚了,就是第3个问题还是不太明白,AND EDX,3 如何和 mod 4 相等?
lw549 2004-08-16
  • 打赏
  • 举报
回复
高位都是0
低位与0011 and操作自然是对4求余了。
Eastunfail 2004-08-16
  • 打赏
  • 举报
回复
寒~~~~~~~

早知道如此简略我就不必那么麻烦的证明了
ehom 2004-08-16
  • 打赏
  • 举报
回复
一个二进制数111111...转成十进制是

2^0+2^1+2^2+2^3+2^4+2^5...从低位开始的第三位后,任意一位出现1,其本身都能整除四,所以整个数对4取模自然就是其低三位的值
Eastunfail 2004-08-16
  • 打赏
  • 举报
回复
别问我为什么要设一个函数Y=X AND NOT ( X AND 3),我自己都糊涂了。
Eastunfail 2004-08-16
  • 打赏
  • 举报
回复
Y=X AND NOT ( X AND 3) 后结果是11B位清0了
根据DeMorgan定律:
Y=X AND ((NOT X) OR (NOT 3))
=>
Y=(X AND (NOT X)) OR (X AND (NOT 3))
=>
Y=0 OR (X AND (NOT 3))
=>
Y=X AND NOT 3
因为最后2位清0了
所以
Y|X = (X SHR 2) SHL 2
Y|X = (X DIV 4) MUL 4
而DIV是整除,余数被消掉了
此时
Y|X = (X DIV 4) MUL 4 = X-(X MOD 4)
X AND NOT 3 = X - (X MOD 4)
因为X AND NOT 3对除了11B位以外的其他位不影响,所以可以分解成:
X AND NOT 3 = X XOR (X AND 3) = X - (X AND 3)
而因为前面计算得到 X AND NOT 3=X - ( X MOD 4)
所以有:
X- (X AND 3)=X - (X MOD 4)
=>
X AND 3 = X MOD 4

Eastunfail 2004-08-16
  • 打赏
  • 举报
回复

Y=X MOD 4
根据模的性质, 0<=Y<=3
而 Y=X AND 3的值域也是 [0,3],定义域和值域相等拉,里两个函数映射关系也不远了

然后再让我想想
crossbow 2004-08-16
  • 打赏
  • 举报
回复
求教...
hsmserver 2004-08-14
  • 打赏
  • 举报
回复
呵呵好学汇编
想搞加解密
买了几本书
还没看呢
要不我也给你讨论讨论
BigAngell 2004-08-14
  • 打赏
  • 举报
回复
学习
crossbow 2004-08-14
  • 打赏
  • 举报
回复
to Eastunfail(龙子龙孙)==(恶鱼杀手) 老大:

谢谢您的关于问题1、2的详细讲解。


to ehom(?!) 老大:

我是把函数复制出来改名再调用,删除CMP ECX,ECX 依然可以正确运行。不知道置ZF=1有什么用,我把这行屏蔽掉依然可以工作,不信你试试。


to ZhangYv(has been killed) 老大:

>SUB是无符号的减法

ShowMessage(IntToStr(CompareStr('fu', 'fuck'))); //但这返回-2

>是保留低2位的值,其它位置0,是屏蔽某些高位的常见做法。这里可以理解成MOD 4

老大能不能再说详细点?有什么经验吗?谢谢。
jpyc 2004-08-14
  • 打赏
  • 举报
回复
只做个单片机的,对PC的不熟悉
flyingmyself 2004-08-14
  • 打赏
  • 举报
回复
汗!
ehom 2004-08-14
  • 打赏
  • 举报
回复
当然有用,你举的例子不够特殊

CompareStr1('Test','')

再去掉CMP ECX, ECX试试?这时候因为一个字符串为空,ECX为0,循环次数为0,CMPSB不会改变ZF,这时候如果ZF=0,就会导致执行后面的MOVZX EDX,BYTE PTR [EDI-1]执行,这也必然导致异常.于是这时候就必须使用CMP ECX, ECX将ZF置为1

但你问的是StrLen中的SUB,不是CompareStr中的,CompareStr当然会出现负数,不看代码,帮助也说的很明白了
加载更多回复(13)

5,386

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧