首页
社区
课程
招聘
[分享]根据外星人C程序改编出的计算圆周率800位的汇编程序
发表于: 2008-11-9 13:15 5989

[分享]根据外星人C程序改编出的计算圆周率800位的汇编程序

2008-11-9 13:15
5989
某天,见到下面一段C程序,4行代码计算出圆周率800位,号称是外星人写的程序:

int a=10000,b,c=2800,d,e,f[2801],g;
main(){for(;b-c;)f[b++]=a/5;
for(;d=0,g=c*2;c-=14,printf("%.4d",e+d/a),e=d%a)
for(b=c;d+=f*a,f=d%--g,d/=g--,--b;d*=b);}

    近日,根据反汇编结果,并根据CPU寄存器的特点,用汇编语言改编了这段程序,也可以计算出圆周率800位:

        .586
        .model flat, stdcall
        option casemap :none
include                MACRO.ASM
includelib        msvcrt.lib
printf        proto C :VARARG
        .data
f        dd 2801 dup(2000)        ;因为有这种定义,省略了for(;b-c;)f[b++]=a/5;
        .code        ;a--->ebx,b、g--->ecx,d--->edi,e--->ebp,e--->esi
start:        xor esi,esi                        ;e=0
                mov ebp,2800                ;c=2800
                mov ebx,10000
@1:                xor edi,edi                ;d=0
                mov ecx,ebp                ;b=c
                @@:        imul edi,ecx        ;d=d*b
                        mov eax,[ecx*4+f]        ;d+=f*a
                        mul ebx       
                        add eax,edi
                        lea ecx,[ecx*2-1]
                        div ecx
                        inc ecx
                        shr ecx,1
                        mov [ecx*4+f],edx        ;f=d%(2b-1)
                        mov edi,eax        ;d=d/(2b-1)
                        loop @b                               
                div ebx       
                add eax,esi                ;e+d/a
                mov esi,edx                ;e=d%a
                invoke printf,CTXT("%.4d"),eax
                sub ebp,14                ;c-=14
                jnz @1               
                ret                        ;控制台程序,最后用这个即可
                end start
编译所用的命令               
;ml /c /coff /nologo pi.asm
;Link /subsystem:console /nologo pi.obj
要自己找一下msvcrt.lib和msvcrt.dll,否则无法使用printf。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
这段C预言不是有人扩展过么
#include < stdio.h>

long a=10000, b, c=2800, d, e, f[2801], g;
main(){
    while(b-c!=0){
        f=a/5;
        b++;
        }
    d=0;
    g=c*2;
    while(g!=0){
        b=c;
        d+=f*a;
        f=d%--g;
        d=d/g--;
        --b;
        while(b!=0){
            d=d*b+f*a;
            f=d%--g;
            d=d/g--;
            --b;
            }
        c-=14;
        printf("%.4d",e+d/a);
        e=d%a;
        d=0;
        g=c*2;
        }
    }
2008-11-11 23:35
0
雪    币: 200
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
第一次看到这段代码,收藏先。。。
lz好兴致,赞一个
2008-11-12 08:24
0
雪    币: 253
活跃值: (250)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
4
又优化了一下,ChopDown 的这段代码和我最后整理出来的思路基本一致,不过我原来没有看过这段,其实前面的 f=a/5完全可以改为f=2000,而在汇编语言中则可以直接定义成有初始值的数组。优化结果如下:

  .586
  .model flat, stdcall
  option casemap :none
include    MACRO.ASM
includelib  msvcrt.lib
printf  proto C :VARARG
  .data
f  dd 2801 dup(2000)  ;因为有这种定义,省略了for(;b-c;)f[b++]=a/5;
  .code  ;a--->ebx,b、g--->ecx,d--->edi,e--->ebp,e--->esi
start:  xor esi,esi      ;e=0
    mov ebp,2800    ;c=2800
    mov ebx,10000
@1:    xor edi,edi    ;d=0
    mov ecx,ebp    ;b=c
    @@:  imul edi,ecx  ;d=d*b
      mov eax,[ecx*4+f]  ;d+=f*a
      mul ebx  
      add eax,edi
      lea edi,[ecx*2-1]
      div edi
      mov [ecx*4+f],edx  ;f=d%(2b-1)
      mov edi,eax  ;d=d/(2b-1)
      loop @b        
    div ebx  
    add eax,esi    ;e+d/a
    mov esi,edx    ;e=d%a
    invoke printf,CTXT("%.4d"),eax
    sub ebp,14    ;c-=14
    jnz @1   
    ret      
   end start
2008-11-13 18:07
0
游客
登录 | 注册 方可回帖
返回
//