打印

HotC51共产儿童团第十五课:菜农点评__HotASM_START__看谁是尿童

[复制链接]
1432|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
HotC51|  楼主 | 2009-3-9 19:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

开课:
xwj 发表于 2009-3-5 12:28 侃单片机 ←返回版面   

17楼: “红杏出墙装疯拳”详解--第一招:

/*---------------------------------------------
    HotTask51系统启动函数
    
void __HotASM_START__(void)
入口: 无
      Keil DPTR = &__HotASM_START__[0]
           R2D1 = DPTR
出口: 无
结果: 二次RETI后继续执行
特点: 本“函数”可以“动态加载”
-----------------------------------------------*/
--老x:上面是注释,在中国上过学的都能看懂,就不用啰嗦了
--观众:这还不啰嗦啊?晕!
--老x:甭晕啊,这都还没开始呢...
HotASM (__HotASM_START__)//(void)        --定义个code区的数组,相当于code const unsigned char __HotASM_START__
                                        --为什么呀?
                                        --为什么?先去看下HotASM.h啊,里面先一招typedef code const unsigned char HotASM_ARRAY;//类型定义
                                                                          然后一招#define HotASM(NAME) HotASM_ARRAY(NAME)[]=
                                        --嗯,象这样的问题老x以后就不再回答了,免得浪费时间,还把老x也累得要死...
{//DPTR保存的是汇编数组函数的首地址__HotASM_START__
#define lable__HotASM_START__Exit 
(    size_CLR_A()  + size_MOV_REG_A()  + size_JZ()  + size_LJMP()  + 2 * size_MOV_A_REG()  + 2 * size_ADD_A()  + 2 * size_PUSH_REG())
--嗯,这个是用来计算跳转多少个字节的,因为后面有个分支,一个分支分支就会有2个出口,有2个出口当然就会有不同的跳转偏移...
--晕,老x今天怎么这么象唐僧啊?
--嗯,那就先不管了,其实老x觉得啊,这样子好麻烦啊,还要把中间跳过的指令都复制过来,还要统计中间的字节数,真是麻烦啊~~~,老x觉得啊,可以有更简单的方法啊,比如直接就RETI啊...
--少啰嗦,快说正题!
--好好,老x接着分析啊~~
    asm_CLR_A(),                    --想不用想,把ACC清零(有什么用呢?)
    asm_MOV_IE_A(),//关中断            --哦,原来是IE=ACC; 关中断。(那...为什么不干脆CLR EA呢?)
    asm_JZ(size_LJMP() - 1),//NOP()    --A为零跳转(这不是那脱裤子排气吗?A肯定为0啊,刚刚才清过呢)
    asm_LJMP(0x5500),//                --跳过去了,永远运行不到
    asm_MOV_A_DPL(),                --ACC=DPL;
    asm_ADD_A(lable__HotASM_START__Exit),//__HotASM_START__0    --加上偏移,进位的话影响CY
    asm_PUSH_ACC(),//压入跳入地址__HotASM_START__0低8位            --ACC入栈,SP加一
    asm_MOV_A_DPH(),//                --ACC=DPH;
    asm_ADDC_A(0),                    --前面加偏移时可能会进位,把可能的进位加进去
    asm_PUSH_ACC(),//压入跳入地址__HotASM_START__0高8位            --ACC入栈,SP又加一;这是堆栈中最高2字节是下一个出口的地址
//lable__HotASM_START__Exit:
    asm_RETI()//(连续调用RETI二次)    --明明只有一次RETI吗,看来老Hotel真是老糊涂了
                                    --RETIRET的作用可大了它的作用就是把堆栈中最高2字节装入PC(程序地址指针寄存器),把SP-2,这样下一个指令就返回到堆栈中最高2字节对应的地址位置继续执行了
                                    --这就相当于一个可以任意设置跳转位置的LJMP,所有的OS可都要玩到这一招哦
};

首先可以看出XWJ很少“反汇编”,而且C51的汇编应该属于“尿童级”。
    asm_CLR_A(),                    --想不用想,把ACC清零(有什么用呢?)
    asm_MOV_IE_A(),//关中断            --哦,原来是IE=ACC; 关中断。(那...为什么不干脆CLR EA呢?)
    asm_JZ(size_LJMP() - 1),//NOP()    --A为零跳转(这不是那脱裤子排气吗?A肯定为0啊,刚刚才清过呢)
    asm_LJMP(0x5500),//                --跳过去了,永远运行不到

在这4句里,隐藏了反逆向技术。
首先,asm_CLR_A(),得到一确定的事情,ACC肯定为0
asm_MOV_IE_A(),//关中断,因为是初始化函数,就应该初始化干净。
否则软中断后,EX0等IE内的5个中断标志不会被清除。
下面这2句谁能看出来???
    asm_JZ(size_LJMP() - 1),//NOP()    --A为零跳转(这不是那脱裤子排气吗?A肯定为0啊,刚刚才清过呢)
    asm_LJMP(0x5500),//                --跳过去了,永远运行不到

脱裤子排屁是臭逆向者的~~~因为此时ACC为0,它跳入了asm_LJMP(0x5500),的第2操作数0x00。
0x00是数据,但代码确实NOP!!!
0x5500就是引诱反汇编去0x5500处折腾的,正常的程序永远不会执行到~~~
这是系列反逆向技术的一招。请团员们切记!!!
大家可以耐心地debug,可以看到好好的反汇编窗口在执行开始没有NOP指令,
单步到JZ后,在单步发现指令列表突然变化了---出现了NOP!!!
试想,团员们用菜农的“250”招后,谁还再来反汇编???
晕都晕死它~~~
俺是“反汇编”的“革命先烈”~~~最近“反水”,所以俺最知道对付“自己人”
~~~
程序虽小,不晕则好。
有时间继续点评其他HotC51Demo内的小程序~~~
注意,每个都有课本上学不到的知识~~~
课毕

HotC51@126.com   2009.3.9于菜地。
团部:
http://group.**/1623/

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

306

帖子

0

粉丝