打开64K程序神话的大门

想必大家都领教过那个用64k显示3d并且还有声音的程序,紫丁香C版版主SwordLea将其反编译,得到了64K的第一层代码,下面是我在紫丁香的文章:

这两天学习了一下老lee反汇编出来的代码,大概弄懂了整个代码的执行流程,贴出来跟大
家交流一下,本人汇编也不是很熟,肯定有不对的地方,还请高人指出。

整个代码主要分三个部分,一个是标记为start的入口函数,一个是标记为sub_155的字函
数,这个函数主要进行一些解码的数据运算,还有就是最后那一大串的db数据,SwordLee
说的对,真正执行的代码其实是这些,之前的start和sub_155就是首先对这些数据解压,
然后重新跳转到解压后的代码开始执行的。

start函数:

seg000:0100                 xor     si, si 
seg000:0102                 mov     di, 2000h 
seg000:0105                 mov     ch, 10h 
seg000:0107                 rep movsw 
作用是从0向2000h传送16个字,这里没有弄懂,不知道为什么一开始要干这个。

seg000:0109                 mov     ax, cs 
seg000:010B                 add     ax, 200h 
seg000:010E                 push    ax 
seg000:010F                 push    113h 
seg000:0112                 retf
跳转到CS+200h:113h,好像是跳到下一句,这里没有看懂。

seg000:0113                 push    cs 
seg000:0114                 pop     ds 
seg000:0115                 mov     si, 1A1h 
seg000:0118                 mov     di, 100h 

指定源地址为cs:1a1h,即db数据序列开始处;目的地址为cs:100h,即dos的com程序指令
开始处,之后的代码就是从si取出一个字节,解压后放到di,显然就是将db数据序列处理
后放到com程序的代码区,最后跳转执行。

seg000:011B                 push    es 
seg000:011C                 push    di 
...
seg000:0154                 retf 
start在解压完毕后跳转到[es:di],即seg000:100h处执行(正是解压后的代码序列),才
开始执行真正的代码


seg000:011D                 mov     ax, 111h 
seg000:0120                 mov     bx, 1321h 
seg000:0123 
seg000:0123 loc_123:                                ; 
seg000:0123                 mov     [bx], ax 
seg000:0125                 dec     bx 
seg000:0126                 dec     bx 
seg000:0127                 dec     ax 
seg000:0128                 jns     short loc_123 

从1321h处开始放置字数据:111h,110h,...0h,这里在sub_155子过程里要用到,可能是某
个解压算法要用的什么表;

之后我们就开始解压了:

seg000:012A                 lodsw 
seg000:012B                 xchg    ah, al 
seg000:012D                 mov     cx, ax 
seg000:012F                 mov     bp, 0FFFFh 
seg000:0132 
        -----si ->ax; ah al交换; cx=ax; bp = 0ffffh

seg000:0132 loc_132:                                ; 
seg000:0132                                         ; 
seg000:0132                 call    sub_155
seg000:0135                 cmp     ax, 100h 
seg000:0138                 jz      short locret_154 
seg000:013A                 jg      short loc_13F 

-------调用sub_155,ax为100h时跳到locret_154(start结束),ax大于100h时到loc_13F
            

seg000:013C                 stosb 
seg000:013D                 jmp     short loc_132 
seg000:013F ;  
          -------ax -> di;然后回到上面的loc_132,进行下一个db的处理
seg000:013F             
seg000:013F loc_13F:                                ; 
seg000:013F                 sub     ax, 0FFh 
seg000:0142                 push    ax 
seg000:0143                 call    sub_155 
seg000:0146                 pop     dx 
seg000:0147                 neg     ax 
seg000:0149                 mov     bx, ax 

    -------ax -=0ffh, 然后调用sub_155, bx = ax的补
seg000:014B 
seg000:014B loc_14B:                                ; 
seg000:014B                 mov     al, es:[bx+di] 
seg000:014E                 stosb 
seg000:014F                 dec     dx 
seg000:0150                 jnz     short loc_14B 
seg000:0152                 jmp     short loc_132 
seg000:0154 ;
            
    --------es:[bx+di]->al,ax ->di,若(--dx)!=0 则重复,否则跳到loc_132


这里对每一个db字节的数据进行一次算术处理。sub_155的参数为cx。每一次都将要解
压的数据放在ax中后将高低字节交换,放到cx中,然后调用sub_155,处理完毕后放在seg000:0100h开始的一段内存内。最后,start调用retf返回到es:di,就是刚才说过的seg000:0100h,这时,这个地址开始的内存中已经是解压好的指令了。

sub_155子过程只是进行了一系列的算术运算,辅助start进行解压。

整个程序大概流程就是这样,说到底这不是真正最后我们看到的效果所执行的代码,还希
望哪位大牛能搞出被解压后的代码让我们大家长长见识 
-------

p.s.我们用Ctrl-C复制到debug,程序刚开始运行后,可以输入Esc回到debug,然后我们就可以使用u指令将解压缩后的代码弄出来,比如头20B的代码如下:

   MOV AX,CS

MOV DS,AX

MOV DI,4248

ADD AX,1000

STOSW

ADD AX,1000

MOV CX,0014

STOSW

INC AH

LOOP 0115

MOV DI,13AE

MOV CX,1FDE

.....

因为最后还是个COM程序,所以不会超过64K,有兴趣的话可以都弄出来 : )

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值