[经验] FAS 20号指令的深入研究

看了tryhi大侠的精华贴 《定义真正意义的可选参数》(http://bbs.mjtd.com/thread-181052-1-1.html)受益匪浅,原来这个不起眼的指令竟然蕴藏玄机。文中对20号指令(十六进制14h)四个参数的作用是这样描述的:
第一字节:表示参数数量+无名变量的数量之和
第二字节:表示允许的最低参数数量
第三字节:表示大参数个数
第四字节:只有00和01两种,00表示为有限参数(默认情况下必然为00),01表示无限参数
经过试验,第二字节和第三字节的描述非常准确,就不做进一步研究了。下面重点研究第一和第四个字节。
用od附加acad.exe进程,跟踪一下14h指令的执行过程,发现相关参数的处理代码如下:(不懂汇编语言的朋友请跳过这一小段代码,直接看后面的结论)
          movzx ax, byte ptr [edi+esi+03]     ;第四个字节
          movzx cx, byte ptr [edi+esi]        ;第一个字节
          and ax, FFFE                        ;第四个字节最低位清零
          shl ax, 07                          ;左移7位,取第四个字节的高七位
          or ax, cx                           ;与第一位相加
          movzx ecx, ax                       ;只保留低16位
          test cx, cx                         ;判断 aa和dd是否为零
          je 574989AC                         ;如为零,跳转到地址574989AC
从上面代码可以看出,第一字节和第四字节不是独立的,是组合在一起使用的。
第四个字节被分成了两部分,一部分和第一字节组合,左移7位与第一字节进行or运算。另一部分,就是最低位的0和1,用来表示有限参数和无限参数。
也就是说,第四字节的高7位是和第一字节组合使用,最低位单独使用。
这样第一个字节和第四个字节组合起来能表示的数值范围是十六进制0-7FFFH,也就是十进制0-32767.
这个数字是做什么用的呢?tryhi大侠认为是表示参数数量+无名变量的数量之和,和晨语探讨,他也这么认为。
我经过跟踪和试验,发现它是函数在初始化时需要清除的无名变量个数,被清除的无名变量内容会变成nil,没有被清除的还是原来的值。
如果程序中要使用无名变量,第一个字节和第四个字节不能同时为0,否则会出现0xC00000005冲突,导致程序不能执行。

重复一下,20号指令的格式如下:(十六进制)
14 aa bb cc dd
其中: bb表示允许的最低参数个数,如果小于这个值,程序出错,显示参数太少。
       cc表示允许的最大参数个数,如果大于这个值,程序也会出错,显示参数太多。
       dd的最低位如果是1表示参数是个表,也就是无限参数,如果是0,不是表,参数是有限的。对于是否有限来说,254和0是一样的,255和1效果一样。
       aa和dd的高7位组合,数值表示程序初始化时需要清除掉的无名变量个数,范围是0-32767。举个例子,如果想表示255个,那就是aa=255,dd=0或1。
如果想表示256,那aa=00,dd=2或3; 2表示有限参数,3表示无限参数。
14h指令的反汇编代码见附件,不懂asm的请不要浪费币:-) 。

原文地址:https://www.cnblogs.com/mjgw/p/12525275.html