• 全部
  • 问答

擂台:用汇编语言计算大数阶乘,程序最小最快者1000分送上

liangbch 2005-07-19 01:37:59
看到汇编版块比较冷清,故设擂比武。其目的一为提高本版人气,二是通过交流,共同提高编程水平。其题目选用计算大数阶乘,一是我对此比较熟悉,二是该算法难度适中,同时涉及到少数dos或者API调用,有一定的实用性和可玩性。

尽管算法很重要,但这里主要比拼的编程能力,即如何以尽可能小的代码完成指定的功能。我在本站刚刚更新了我的程序,快速阶乘计算器。新版增加了一个mini版。mini版分dos和windows两个程序。dos 版的可执行文件仅仅323字节。windows版的可执行文件仅为1224字节。这两个版本均提供一个等价的.c程序源代码和制作过程说明文档。

由于我的程序非小巧,并且包含等价的c程序,借助反汇编工具很容易还原成汇编原程序,但我希望大家最好独立思考,自主编程,我不建议在我程序的基础上修改。

欢迎高手打擂,欢迎有兴趣的人参与讨论。

评分标准暂定如下:
dos版总分:400,windows 版总分:600。对于dos版,凡程序小于的我的程序者得分80%,程序大小和速度均胜于我者,得分100%.对于windows版,凡是用编译器生成的PE文件所含代码和数据小于我的程序者得分60%,最终程序小于我的程序者,再送剩余的40%。如多人满足条件,只送成绩最好者。如没人达到要求。则酌情送分给前几名。

擂台截至日期暂定为10月底。
...全文
1285 点赞 收藏 45
写回复
45 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
ashchen 2005-10-10
有没有比C效率更高,比汇编更友好的语言?
回复
csdsjkk 2005-10-10
那位贴个100!的结果出来
回复
Leomaxking 2005-10-10
顶。。。
回复
耙子 2005-10-10
阶乘结果后面很多是0 (二进制也是),是否可以用类似科学技术法的方法在有限的空间来保存更多的结果。
回复
liangbch 2005-10-09
先自己顶一下!
回复
liangbch 2005-09-06
up
回复
僵哥 2005-08-28
汗一个先
偶学汇编只是为了程序入门,工作环境当中更是使用的语言更复杂多样,都没一个能用得灵活的,在这里帮顶!
回复
casazaft 2005-08-25
lvqinhai(阿海) 我不懂汇编....不过,这样会不会溢出
回复
lvqinhai 2005-08-25
晕!这也出来招摇!
eax= offser n
ebx= offset (n+1)
ecx=n+1
a:
edx= eax * ebx
dec ecx
jnz ecx,0


回复
liangbch 2005-08-24
自己顶。
回复
liangbch 2005-08-19
如果回贴较多,我将公布缩小PE文件的大小的一些技巧。
回复
liangbch 2005-08-16
下面是windows版的文件内容,该文件为PE格式的执行文件,大小仅为896byte,为了缩小文件尺寸,除了优化代码外,在了解PE文件格式的基础上,使用了很多技巧。具体这个文件的特点和使用的技巧将在以后公布。感兴趣者也可使用dumppe 或者其它PE工具分析一个这个文件的特点。
这个程序可计算到10万的阶乘,计算速度比dos版更快。
PE文件生成方法,将下面的内容另存为winfac.txt,在dos命令行输入debug <winfac.txt 可得到winfac.e, 最后,将winfac.e 重命名为winfac.exe即可。

e0100 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00
e0110 B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
e0120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0130 00 00 00 00 00 00 00 00 00 00 00 00 78 00 00 00
e0140 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68
e0150 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F
e0160 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20
e0170 6D 6F 64 65 2E 0D 0A 24 50 45 00 00 4C 01 02 00
e0180 CE 8E 01 43 00 00 00 00 00 00 00 00 C8 00 0F 01
e0190 0B 01 05 0C 00 02 00 00 00 2A 0A 00 00 00 00 00
e01A0 20 10 00 00 00 10 00 00 00 10 00 00 00 00 40 00
e01B0 00 10 00 00 00 02 00 00 04 00 00 00 00 00 00 00
e01C0 04 00 00 00 00 00 00 00 00 50 0A 00 00 02 00 00
e01D0 00 00 00 00 03 00 00 00 00 00 10 00 00 10 00 00
e01E0 00 00 10 00 00 10 00 00 00 00 00 00 0D 00 00 00
e01F0 00 00 00 00 00 00 00 00 F0 10 00 00 28 00 00 00
e0200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0250 00 10 00 00 18 00 00 00 21 2E 74 78 74 00 00 00
e0260 80 01 00 00 00 10 00 00 00 02 00 00 00 02 00 00
e0270 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 60
e0280 2E 64 61 74 61 00 00 00 04 28 0A 00 00 20 00 00
e0290 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00
e02A0 00 00 00 00 40 00 00 C0 50 BF FC 3F 43 00 33 C9
e02B0 41 89 0F 49 BE FC 3F 43 00 AD F7 E3 03 C1 83 D2
e02C0 00 F7 F5 89 56 04 8B C8 3B F7 73 ED 0B C0 74 05
e02D0 83 EF 04 89 07 33 C9 4B 75 DA 8D 6F FC BE FC 3F
e02E0 43 00 BF FF 47 4A 00 AD B1 09 33 D2 F7 35 18 10
e02F0 40 00 83 C2 30 88 17 4F E2 F0 3B F5 73 E9 5B C3
e0300 3C 11 00 00 48 11 00 00 56 11 00 00 64 11 00 00
e0310 30 11 00 00 00 00 00 00 0A 00 00 00 00 CA 9A 3B
e0320 33 DB BF 00 40 43 00 BE 00 20 40 00 53 57 6A 10
e0330 68 04 11 40 00 6A 07 E8 96 00 00 00 53 57 6A 0C
e0340 56 6A 03 E8 90 00 00 00 33 C9 33 C0 56 0F B6 0E
e0350 83 E9 30 83 F9 09 77 14 3D 10 27 00 00 77 70 F7
e0360 25 18 10 40 00 03 C1 46 8B FE EB E1 0B C0 74 5F
e0370 50 BE 58 01 40 00 B9 06 00 00 00 F3 A4 5B 5E 51
e0380 68 80 00 00 00 6A 02 51 51 68 00 00 00 40 56 E8
e0390 4A 00 00 00 0B C0 74 2E 8B 2D 1C 10 40 00 FD E8
e03A0 04 F1 FF FF 47 80 3F 30 74 FA B9 00 48 4A 00 2B
e03B0 CF 6A 00 68 00 48 4A 00 51 57 53 E8 12 00 00 00
e03C0 53 E8 1E 00 00 00 33 C0 50 E8 1C 00 00 00 C3 5E
e03D0 EB F4 FF 25 10 10 40 00 FF 25 00 10 40 00 FF 25
e03E0 04 10 40 00 FF 25 08 10 40 00 FF 25 0C 10 40 00
e03F0 18 11 00 00 00 00 00 00 00 00 00 00 72 11 00 00
e0400 00 10 00 00 6E 3D 3F 28 30 3C 6E 3C 3D 31 30 30
e0410 30 30 30 29 00 00 00 00 3C 11 00 00 48 11 00 00
e0420 56 11 00 00 64 11 00 00 30 11 00 00 00 00 00 00
e0430 9E 02 57 72 69 74 65 46 69 6C 65 00 F7 01 52 65
e0440 61 64 46 69 6C 65 00 00 30 00 43 72 65 61 74 65
e0450 46 69 6C 65 41 00 1A 00 43 6C 6F 73 65 48 61 6E
e0460 64 6C 65 00 80 00 45 78 69 74 50 72 6F 63 65 73
e0470 73 00 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C 00 00
r cx
380
n winfac.e
w
q
回复
blownewbee 2005-08-14
liangbch(宝宝):
高手,先赞一个!
Up
回复
langziji 2005-08-11
有空研究一下,不过我不会汇编,会JAVA
回复
liangbch 2005-08-11
zara 果然聪明,我的做法恰如你所言。在fac3.com,我的初始化部分(输出提示信息,输入数串,生成文件名并打开文件)是放在程序后部的。程序第一条指令是一条跳转指令,直接跳到初始化部分,初始化完成后,再跳到文件开头。在计算部分,文件后部的代码和初始化的数据将被覆盖。虽然增加了2条跳转指令,但文件总长度并不增加。原因是:在源码中,有一些跳转跨度大于+/-127的条件跳转指令,这时,汇编器将生成一条件跳转指令和jmp指令,而将初化部分指令后置后,这些条件跳转指令跨度将小于128,故指令长度缩短,正好抵消了新增的2条指令。例子同下:

jz far_1
mov ax,cx

编译后如下:
jnz next
jmp far_1 ;3字节的跳转令,跳转范转可达+/- 32767
next:
mov ax,cx

至于将栈移到PSP,我并没有采用。一是因为我对psp结构不了解,不敢轻举妄动。二是会使文件增加3个字节的长度。不过,此法确实可行,我今天刚试过。方法是:在初始化部分开头,插入一条指令:mov esp,0feh.
至于fac3_2.com,用了两个技巧,1是另开一个完整的64K的段,将ds,es指向这个段,2是在计算过程不存储计算结果的尾随0,n的阶乘共[n/5]+[n /25] +[n/ 125] +[n /625]+...个0。
fac3.com 和fac3_2.com 的内容一并贴上:
------------------------------------------------------
e0100 EB 64 BE 66 01 33 C9 8B 04 F7 E3 03 C1 83 D2 00
e0110 F7 F7 89 14 46 46 8B C8 33 D2 3B F5 76 E9 0B C0
e0120 75 EE 8D 6C FE 4B 75 DA 5B 8B F5 4D 4D FD AD B9
e0130 04 00 BF 03 01 33 D2 57 BF 0A 00 F7 F7 5F 80 C2
e0140 30 88 15 4F E2 EF B1 05 47 49 3B F5 75 05 80 3D
e0150 30 74 F5 8B D7 B4 40 CD 21 81 FE 66 01 73 CF B4
e0160 3E CD 21 CD 20 90 BE B6 01 8D 54 FE B4 09 CD 21
e0170 B4 0A CD 21 33 C0 BD 0A 00 56 8A 0C 80 E9 30 80
e0180 F9 09 77 0E 3D 7F 0C 77 DA F7 E5 03 C1 46 8B FE
e0190 EB E8 0B C0 74 CD 5A 50 BE C3 01 B1 06 F3 A4 B4
e01A0 3C CD 21 5B 72 BD 50 BD 66 01 41 89 4E 00 BF 10
e01B0 27 E9 4E FF 6E 3D 3F 28 30 3C 6E 3C 33 32 30 30
e01C0 30 29 24 21 2E 74 78 74 00
r cx
C9
n fac3.com
w
q
------------------------------------------------------
e0100 E9 8B 00 BE 06 00 33 C9 39 0C 75 11 56 AD AD 89
e0110 44 FC 3B F5 76 F8 5E 83 44 FE 04 4D 4D 8B 04 F7
e0120 E3 03 C1 83 D2 00 F7 F7 89 14 46 46 8B C8 33 D2
e0130 3B F5 76 E9 0B C0 75 EE 8D 6C FE 4B 75 C5 FD 5B
e0140 8B F5 4D 4D AD B1 04 BF 03 00 33 D2 57 BF 0A 00
e0150 F7 F7 5F 80 C2 30 88 15 4F E2 EF B1 05 47 49 3B
e0160 F5 75 05 80 3D 30 74 F5 8B D7 B4 40 CD 21 83 FE
e0170 06 73 D1 8B 0C 0B C9 74 0F 33 FF FC B0 30 51 F3
e0180 AA 59 33 D2 B4 40 CD 21 B4 3E CD 21 CD 20 BE EB
e0190 01 8D 54 FE B4 09 CD 21 B4 0A CD 21 33 C0 BD 0A
e01A0 00 56 8A 0C 80 E9 30 80 F9 09 77 0E 3D 4C 0D 77
e01B0 DB F7 E5 03 C1 46 8B FE EB E8 0B C0 74 CE 5A 50
e01C0 BE F8 01 B1 06 F3 A4 B4 3C CD 21 5B 72 BE 50 8C
e01D0 D8 05 00 10 50 1F 50 07 BF 06 00 8B EF 89 4D FE
e01E0 41 89 0D BF 10 27 E9 1A FF 6E 3D 3F 28 30 3C 6E
e01F0 3C 33 34 30 35 30 29 24 21 2E 74 78 74 00
r cx
FE
n fac3_2.com
w
q
回复
zara 2005-08-10
呵呵, 见笑了, 虽然我不知道你是怎么有这样的印象的, 除了这个帖子, 以前好像没有打过交道的吧.

本来自己也不是学的这个方面的, 只是当初有些无聊和兴趣, 才自己看了些, 对其中的些艰辛颇有些感触, 尤其是自己一个人看, 没有别人可以指点的时候. 到这里来过之后, 就把这里当做了自己的一个习惯了. 所以, 见到些自己知道的问题, 就会尽可能地说下自己的看法, 希望能够对之有点儿帮助.

对于 fat3.com 的方法, 可能是把堆栈挪到 PSP 中; 将程序的初始化部分放到程序的最后, 这样这部分就可以被最后的数据覆盖掉而不至出错. 至于其它的方法, 就想不到了. 其实, 我想直接在后面开个完整的 64K 的空间不是更合理的吗, 因为, 现在的状况, 64K 的内存应该不是问题的, 限制在这个大小只是访问操作上的方便
回复
liangbch 2005-08-10
to zara:
素闻zara基本功扎实,为人热情。上次17000的限制被一眼看出。这次请您猜猜,fac3.com如何做到将计算范围增加到31999的。
说明:若以一个word保存4位数字,31999!共130266位,需要32567 word,计65134字节,加上程序长度(201),栈长度(最小需28字节,win2000实测),以及com 从100h处加载,总长度已超过64K的限制。

可以告诉你,为了简化代码,一些将导致文件增大的方法并没有使用。

fac3_2.com使用的方法更多一些,计算范围更大,不妨也请你猜猜用了那些方法。
回复
liangbch 2005-08-10
经过几天的努力,再度将文件大小从172缩小至161字节,并衍生出3个新的版本。
fac2.com: 可计算1-17000的阶乘。总共161字节,其中代码:140byte,初始化数据21byte。
fac2_2.com: fac2.com的简化版,不显提示信息,以牺牲界面为代价,使程序更小。总共139字节,其中代码:117byte,初始化数据12byte.

fac3.com, 和fac2.com 相比,计算范围更大,可计算1-31999的阶乘; 速度更快,大约是fac2.com的四倍。总共201字节,其中代码:180byte,初始化数据21byte.

fac3_2.com fac3.com加强版,计算范围更大,可计算1-34049的阶乘,程序更加复杂,但大小仍控制在256byte之内,总共255字节。其中代码:234byte,初始化数据21byte.

下面贴出前两个程序

程序fac2.com,使用方法,将下面的内容存为fac2.txt,在dos命令行输入debug <fac2.txt即得到fac2.com

e0100 BA 92 01 B4 09 CD 21 BE 94 01 8D 54 FE B4 0A CD
e0110 21 33 C0 BD 0A 00 56 8A 0C 80 E9 30 80 F9 09 77
e0120 0E 3D A4 06 77 64 F7 E5 03 C1 46 8B FE EB E8 0B
e0130 C0 74 57 5A 50 BE 8C 01 B1 06 F3 A4 B4 3C CD 21
e0140 5B 72 47 50 81 C7 57 FC C6 05 01 8B F7 33 C9 56
e0150 33 C0 8A 04 F7 E3 03 C1 83 D2 00 F7 F5 88 14 8B
e0160 C8 4E 33 D2 3B F7 73 E8 0B C0 75 EF 8D 7C 01 5E
e0170 4B 75 DA 57 80 05 30 47 3B FE 76 F8 5A 8B CF 2B
e0180 CA 5B B4 40 CD 21 B4 3E CD 21 CD 20 21 2E 74 78
e0190 74 00 6E 3D 3F 28 30 3C 6E 3C 31 37 30 30 31 29
e01A0 24
r cx
A1
n fac2.com
w
q


程序fac2_2.com,使用方法,将下面的内容存为fac2_2.txt,在dos命令行输入debug <fac2_2.txt即得到fac2_2.com

e0100 BE 8D 01 8D 54 FE B4 0A CD 21 33 C0 BD 0A 00 56
e0110 8A 0C 80 E9 30 80 F9 09 77 0E 3D A4 06 77 64 F7
e0120 E5 03 C1 46 8B FE EB E8 0B C0 74 57 5A 50 BE 85
e0130 01 B1 06 F3 A4 B4 3C CD 21 5B 72 47 50 81 C7 57
e0140 FC C6 05 01 8B F7 33 C9 56 33 C0 8A 04 F7 E3 03
e0150 C1 83 D2 00 F7 F5 88 14 8B C8 4E 33 D2 3B F7 73
e0160 E8 0B C0 75 EF 8D 7C 01 5E 4B 75 DA 57 80 05 30
e0170 47 3B FE 76 F8 5A 8B CF 2B CA 5B B4 40 CD 21 B4
e0180 3E CD 21 CD 20 21 2E 74 78 74 00 0A
r cx
8C
n fac2_2.com
w
q
回复
mengxiangfengwz 2005-08-07
小儿科
回复
zara 2005-08-07
结果在当前目录下的 ??!.txt 文件里, ?? 是你输入的数值
回复
相关推荐
发帖
汇编语言
创建于2007-08-27

2.0w+

社区成员

汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
申请成为版主
帖子事件
创建了帖子
2005-07-19 01:37
社区公告
暂无公告