吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2463|回复: 4
收起左侧

[其他转载] 【老刘谈算法004】拿目标地址传送指令进行快速运算的骚操作-字符串转双字函数分析(1)

  [复制链接]
老刘 发表于 2019-3-4 13:07
本帖最后由 老刘 于 2019-3-4 13:24 编辑

快速运算与x86内存定位公式

在编写x86汇编时,你是否有这样的苦恼?

  • 做简单的乘法运算,都需要写很多行,还要将寄存器中的数据导来导去。
  • 将寄存器放到其它寄存器中并加减一个数,都要写mov,add两条指令。

其实,借助x86灵活的内存定位方式,以及一个被“屈才”了的汇编指令,这些操作可以在一条汇编指令中实现

地址定位公式

在8086汇编中,汇编指令支持简单的“地址定位公式”:

  1. [bx]
  2. [bx+立即数]
  3. [si/di+bx+立即数]
  4. ...

在x86中,地址定位支持了简单的乘法,寄存器的限制也变得宽松:

  1. [立即数]
  2. [寄存器] (可以是8个(32位)通用寄存器中的任意一个)
  3. [寄存器+立即数]
  4. [寄存器1*{2,4,6,8}+寄存器2]
  5. [寄存器1*{2,4,6,8}+寄存器2+立即数]

x86的灵活度大大提升,便利了内存的存取,也给了我们可乘之机。

LEA指令

说来有趣,绝大部分文档对LEA指令作用的说明中,只是将其称作有效地址传送指令,而笔者认为更贴切的说明应是“简单加乘运算指令”。
虽然在指令的实际执行中,LEA大部分情况还是被用来获得局部变量、数组元素等的地址,但cpu并不会检测所得“地址”是否可用,所以即使得到的是无效地址,指令也可以正常执行。
LEA指令在CPU内部执行的操作,便是把地址定位公式计算出来,放到目标寄存器中,由于无效地址也不影响执行,LEA便可以计算满足地址定位公式的表达式

让我们解决刚开始提出的问题:
A.将一个寄存器(如ecx)的值放到其它寄存器(如edx)中并加一个数。
正常实现:

Mov Edx,Ecx
Add Ecx,idata

LEA实现:

Lea Ecx,[Edx+idata]

B:进行简单的加乘运算。
1)eax*=3
正常实现:

Push Eax
Add Eax,Eax
Add Eax,[Esp]
Add Esp,4

Lea实现:

Lea Eax,[Eax*2+Eax]

2)edx+=eax*8
正常实现:

Push Eax
Push Edx
Mov Edx,8
Mul Edx
Pop Edx
Add Edx,Eax
Pop Eax

Lea实现:

Lea Edx,[Eax*8+Edx]

可见,进行简单加乘运算时,用Lea更明了,简洁,效率也高些。

局限性

  • LEA指令不会按照结果改变标志位,想要根据结果进行条件跳转还需要另加判断。
  • 64位结果中的高32位会被丢弃。
  • 乘法为无符号数乘法。

其它

笔者才疏学浅,若有错误疏漏,希望各路大神不吝赐教。
实例代码(出自MASM32Lib):

; #########################################################################

  ; ---------------------------------------------------------------
  ;      本程序最初由 Tim Roberts 编写
  ;
  ;         Alexander Yackubtchik 优化了部分代码
  ; ---------------------------------------------------------------

    .486
    .model flat, stdcall  ; 32 bit memory model
    option casemap :none  ; case sensitive
    .code

; #########################################################################

atodw proc String:DWORD

  ; ----------------------------------------
  ; 十进制转dword
  ; eax储存返回值
  ; ----------------------------------------

    push esi
    push edi

    xor eax, eax
    mov esi, [String]
    xor ecx, ecx
    xor edx, edx
    mov al, [esi]
    inc esi
    cmp al, 2D        ;检测负号
    jne proceed        ;不是负号就跳转
    mov al, byte ptr [esi]
    not edx        ;FFFFFFFF
    inc esi
    jmp proceed

  @@: 
    sub al, 30h        ;ascii->byte
    lea ecx, dword ptr [ecx+4*ecx]        ;ecx*=5
        lea ecx, dword ptr [eax+2*ecx]        ;ecx=ecx*2+eax
    mov al, byte ptr [esi]
    inc esi

  proceed:
    or al, al
    jne @B        ;非0(没处理完)上跳
    lea eax, dword ptr [edx+ecx]
    xor eax, edx

    pop edi
    pop esi

    ret

atodw endp

; #########################################################################

end

免费评分

参与人数 2吾爱币 +4 热心值 +2 收起 理由
如南风过境z + 1 + 1 用心讨论,共获提升!
苏紫方璇 + 3 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

迷雾 发表于 2019-3-4 13:19
感谢,非常有用
嘟嘟侠 发表于 2019-3-4 13:49
吾爱支持 发表于 2019-3-4 16:05
本帖最后由 吾爱支持 于 2019-3-4 16:07 编辑

感谢老刘分享……一直没勇气学汇编……
没心心了,送上鲜花和敬意!!!
 楼主| 老刘 发表于 2019-3-4 21:21
嘟嘟侠 发表于 2019-3-4 13:49
还有部分没弄明白

具体哪部分呢?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 03:43

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表