深析DELPHI in 操作实现

群友探讨到这个问题顺便有空分析了下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范围的数据。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值