[原]深析DELPHI in 操作实现

Reverse.King 2010-07-27 03:31:36
加精
群友探讨到这个问题顺便有空分析了下delphi编译器的实现方式,有错误地方敬请指出。
function AnsiStrInCharSet(ch: char; CharSet: TSysCharSet): boolean;
begin
Result := ch in CharSet;
end;
测试调用:if AnsiStrInCharSet('a', ['a'..'z']) then ...

实际编译器翻译为以下代码:
0045BF7A |. F3:A5 rep movs dword ptr es:[edi], dword ptr [esi] ;
复制ESI( ['a'..'z']) 到BT指令标志判断dest操作数,也就是CharSet: TSysCharSet 的内容由编译器固定编译为一个位信息常量,该常量长度为32byte,定义结构为:

TBitInfoField =array [0..7] of dword;

暂称该常量为BitInfoField:TBitInfoField 具体规则后面讲述。

0045BF7C |. 0FB6C0 movzx eax, al ;
赋值到BT指令标志判断src操作数,也就是ch: char

0045BF7F |. 0FA345 E0 bt dword ptr [ebp-20], eax ;
[ebp-20] 实际指向BitInfoField,eax是位数,作用就是把BitInfoField的第eax位送CF标志

比如['a'..'z']编译器编译的BitInfoField为:
0012F588 00 00 00 00 00 00 00 00 00 00 00 00 FE FF FF 07 ............?
0012F598 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

[#0..#255]编译器编译的BitInfoField为:
0012F588 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
0012F598 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 

为什么编译器会这么编译呢?因为bt指令是一个标志测试指令具体语法格式为:
BT r/m16,r16
将所选的位存储到 CF 标志

BT r/m32,r32
将所选的位存储到 CF 标志

BT r/m16,imm8
将所选的位存储到 CF 标志

BT r/m32,imm8
将所选的位存储到 CF 标志
这里有两个公式确定位值:

1. BIdx= BitOffset div 32

2. BBit= BitOffset mod 32




我们这里的in编译器使用的是 BT m32,r32格式,它的作用就是把m32内存中BitInfoField[BIdx(r32)]常量的数据的第BitInfoField[BBit(r32)]位送CF标志.
假设枚举范围是['a'..'z'] 则BitInfoField为:

00 00 00 00 00 00 00 00 00 00 00 00 FE FF FF 07
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00



'a' in ['a'..'z'] 最后转换成的CPU指令应该是:

bt dword ptr [BitInfoField] , eax ; eax= $61



因为 'a'的Ascll码为:$61 根据公式: BIdx = $61 div 32 = 3 , BBit= BitOffset mod 32 =1

BitInfoField[BIdx=3 ] = $7FFFFFE 转换为二进制为:00000111111111111111111111111110

BBit = 1

00000111111111111111111111111110

31-------------------------------0

那么 bt dword ptr [BitInfoField] , $61 就是把下面标志传送到CF标志寄存器


000001111111111111111111111111[1]0

31-------------------------------0

所以CF =1


这样就完成了'a' in ['a'..'z'] 的判断。

根据此原理可以推导出 delphi的 char in ['a'..'z'] 和 char in ['a'..'z','1'..'9'] 执行效率是一样的

因为['a'..'z','1'..'9'] 的BitInfoField为:

00 00 00 00 00 00 FE 03 00 00 00 00 FE FF FF 07

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00



当判断任意字符 bt dword ptr [BitInfoField] , BitOffset

通过公式:


1. BIdx= BitOffset div 32

2. BBit= BitOffset mod 32


计算出BIdx 和BBit 只需把相应标志位传送到CF即完成。

总结DELPHI in 操作效率比pos操作效率要高很多,并且效率不被枚举元素个数和多少影响,缺点是只能判断0-255范围的数据。
...全文
3129 86 打赏 收藏 转发到动态 举报
写回复
用AI写文章
86 条回复
切换为时间正序
请发表友善的回复…
发表回复
gaocaigs 2011-08-30
  • 打赏
  • 举报
回复
每天回帖即可获得10分可用分
wf2833 2010-08-04
  • 打赏
  • 举报
回复
nan
qulun 2010-08-03
  • 打赏
  • 举报
回复
每天回帖即可获得10分可用分
malfe 2010-08-02
  • 打赏
  • 举报
回复
顶下,可惜看不懂,还没学汇编
singlexinglove 2010-08-02
  • 打赏
  • 举报
回复
顶一下 支持delphi
macklau 2010-08-02
  • 打赏
  • 举报
回复
学习了
olyhome 2010-08-02
  • 打赏
  • 举报
回复
想学Delphi,但不知道从何入手,,请高手提点!
wx343632091 2010-08-02
  • 打赏
  • 举报
回复
不明白
wchsadtn 2010-07-31
  • 打赏
  • 举报
回复
不懂编译,能写的更详细更好
delvel1 2010-07-31
  • 打赏
  • 举报
回复
看不懂 顶顶
kazarus 2010-07-31
  • 打赏
  • 举报
回复
顶一下楼主专研的精神.
萧风晓妖 2010-07-30
  • 打赏
  • 举报
回复
好帖~ 顶 10分可用分
luo_342815 2010-07-30
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 jacky199711 的回复:]

我是个菜鸟 Delphi是开发语言还是开发环境啊
[/Quote]
environment!
  • 打赏
  • 举报
回复
你是niuniuren,编译原理学完考完就忘光光了,你还分析编译器如何编译的,haoku哦
liosten 2010-07-30
  • 打赏
  • 举报
回复
Delphi 还是有价值的,支持楼主
hzdok 2010-07-30
  • 打赏
  • 举报
回复
来拿分的...haha
taxi 2010-07-30
  • 打赏
  • 举报
回复
顶,价值。
任付江 2010-07-30
  • 打赏
  • 举报
回复
学过一段时间啊!呵呵,现在在学java
iamduo 2010-07-29
  • 打赏
  • 举报
回复
[Quote=引用 55 楼 codegame 的回复:]
引用 54 楼 llwlz 的回复:
路过,这语言能做什么

可以做你不会的。 you are very naive!!
[/Quote]
确实如此。
O(∩_∩)O~
wbx419 2010-07-29
  • 打赏
  • 举报
回复
顶一下!!!!!!!!!!!!!牛人
加载更多回复(53)

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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