分享
 
 
 

组合语言之艺术8

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

附录二 程式语言效率分析

以下为利用ASSEMBLY,BASIC,PASCAL,C,FORTRAN 等程式语言,将一个24x 24之点阵字形,放大成为48x 48,并分别比较其处理速度、占用空间以及制作时间。

为了正确计算执行时间,特意作 10,000 次处理,至于指定的24x 24字形,则假设为一空格。

一、ASSEMBLY

组合语言变化无穷,先以一般的作法,用点阵位移来处理。

1: PAGE 60, 132

2: CG SEGMENT

3: BUFIN DB 72 DUP(0)

4: BUFOT DB 72*4 DUP(0)

5: ASSUME CS:CG,DS:CG,ES:CG

6: START:

7: MOV AX,CG

8: MOV DS,AX

9: MOV ES,AX

10: CLD

11: MOV BP,10000 ; 处理10,000次

12: S3:

13: SUB CX,CX

14: MOV BX,CX

15: MOV DX,1803H ; 计数用

16: MOV SI,OFFSET BUFIN ; 24*24 点阵起始位址

17: MOV DI,OFFSET BUFOT ; 预定48*48储存位址

18: MVBYTE:

19: MOV BH,DL ; 做三列

20: MVDB:

21: LODSB ; 取原点阵

22: MOV BL,AL

23: MOV CL,8 ; 做八位元

24: MVDB1:

25: RCL BL,1 ; 左移一次

26: PUSHF ; 保存状态

27: RCL AX,1 ; 两字同时左移一次

28: POPF ; 取出原移位状态

29: RCL AX,1 ; 再一次,得双位点值

30: LOOP MVDB1 ; 八次回路

31: STOSW ; 存入

32: MOV [DI+4],AX ; 上下放大一行

33: DEC BH ; 共 3列

34: JNZ MVDB

35: ADD DI,6 ; 移向次行

36: DEC DH

37: JNZ MVBYTE ; 共24行

38: DEC BP ; 执行10,000次

39: JNZ S3 ; 完成

40: MOV AX,4C00H

41: INT 21H

42: CG ENDS

43: END START

本程式制作时间,为十五分钟。

经汇编后,得934 字元的执行程式,执行耗时14.5秒。

若将上段程式加以分析,可以发现到此段程式执行时间全部浪费在23至30这一段「回路」中。为了增加速度,可以将空间加大,避开回路,连续执行八次「移位」动作如次:

23: RCL BL,1

24: RCL AX,1

25: SHL AX,1

26: 同上共八次

47: MOV CX,AX ; AX中为单位元值

48: SHR CX,1 ; CX得到双位元点阵值

49: OR AX,CX ; 双位元点阵合并

似此,程式增大了36字元,但执行时间却减少为 7.1秒,速度快了一倍!

是不是还是更好的方法呢?相信一定多得不计其数。比如说,我们已知原点阵放大一倍后点形为「双点」,以双点做表,取其对应之值,即可免除各点移位的手续,再将原程式第18条以下改为:

18: VT2:

19: CALL MVBYTE ; 放大一行

20: SUB SI,3 ; 纵向尚须放大一次

21: CALL MVBYTE ; 再放大一行

22: DEC DH ; 完成否?

23: JNZ VT2 ; 再做

24: RET ; 完成

25: MVBYTE:

26: MOV CL,DL ; 一行有三字元

27: MVDB:

28: LODSB ; 取一字元

29: MOV AH,AL ; 分置两处

30: AND AX,0FF0H ; AH,AL 各取四位元

31: SHR AL,1 ; 右移四次还原

32: SHR AL,1

33: SHR AL,1

34: SHR AL,1

35: MOV BL,AL

36: MOV AL,BYTETB[BX] ; 左字元取预设表值

37: MOV BL,AH

38: MOV AH,BYTETB[BX] ; 右字元取表值

39: STOSW ; 得二字元置缓冲器中

40: LOOP MVDB ; 做三次

41: RET

42 ; 转换表

43: BYTETB DB 000H,003H,00CH,00FH,030H,033H,03CH,03FH

44: DB 0C0H,0C3H,0CCH,0CFH,0F0H,0F3H,0FCH,0FFH

45: CG ENDS

46: END START

再换个方法,因为有个XALT的指令,是专为这种程式所设计的。由第25条起,调整如下:

25: MVBYTE:

26: MOV CL,4 ; 供AL左移四位用

27: MOV BX,OFFSET BYTETB

28: MVDB:

29: LODSB ; 取一字元

30: MOV AH,AL ; 分置两处

31: AND AX,0F00FH ; AH,AL 各取四位元

32: SHR AL,CL

33: XLAT ; 将[BX+AL]值放AL中

34: XCHG AL,AH

35: XLAT

36: STOSW

37: DEC DL

38: JNZ MVDB

如此,执行程式959 字元,执行速度3.2 秒,效率更佳。

上述程式的缺点为:在循环过程中,速度有所损失,而且用四位元查表也费事耗时。如果用一字元查表,则需增大「表」的对应值,再改为「总表」的方式,一次即可查到。且由第20行改起,并力求指令的精简,如:

20: MOV DX,OFFSET BYTETB

21: MVDB:

22: LODSB

23: SUB AH,AH

24: SHL AX,1 ; 一字元须变为二字元

25: ADD AX,DX ; 之位置以查表

26: MOV BX,AX ; BX可供间接定址用

27: MOV AX,[BX] ; 以一字元查表值

28: STOSW ; 查妥存入第一行

29: MOV [DI+4],AX ; 上下再重复一行

30: LODSB

31: SUB AH,AH ; 处

32: SHL AX,1 ; 理

33: ADD AX,DX

34: MOV BX,AX ; 材

35: MOV AX,[BX] ; 二

36: STOSW ; 列

37: MOV [DI+4],AX ;

38: LODSB ;

39: SUB AH,AH ; 处

40: SHL AX,1 ; 理

41: ADD AX,DX

42: MOV BX,AX ; 材

43: MOV AX,[BX] ; 三

44: STOSW ; 列

45: MOV [DI+4],AX ;

46: ADD DI,6 ; 再处理下一行

47: LOOP MVDB ; 共24次

48: DEC BP ; 做10,000次

49: JNZ S3 ; 完成

50: MOV AX,4C00H

51: INT 21H

52: RET

程式到此为止,下面还有一转换总表,可供各程式共用。

1:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

2:; 转 换 表 ;

3:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

4: BYTETB LABEL WORD

5: DB 000H,000H,000H,003H,000H,00CH,000H,00FH

6: DB 000H,030H,000H,033H,000H,03CH,000H,03FH

7: DB 000H,0C0H,000H,0C3H,000H,0CCH,000H,0CFH

8: DB 000H,0F0H,000H,0F3H,000H,0FCH,000H,0FFH

9: DB 003H,000H,003H,003H,003H,00CH,003H,00FH

10: DB 003H,030H,003H,033H,003H,03CH,003H,03FH

11: DB 003H,0C0H,003H,0C3H,003H,0CCH,003H,0CFH

12: DB 003H,0F0H,003H,0F3H,003H,0FCH,003H,0FFH

13: DB 00CH,000H,00CH,003H,00CH,00CH,00CH,00FH

14: DB 00CH,030H,00CH,033H,00CH,03CH,00CH,03FH

15: DB 00CH,0C0H,00CH,0C3H,00CH,0CCH,00CH,0CFH

16: DB 00CH,0F0H,00CH,0F3H,00CH,0FCH,00CH,0FFH

17: DB 00FH,000H,00FH,003H,00FH,00CH,00FH,00FH

18: DB 00FH,030H,00FH,033H,00FH,03CH,00FH,03FH

19: DB 00FH,0C0H,00FH,0C3H,00FH,0CCH,00FH,0CFH

20: DB 00FH,0F0H,00FH,0F3H,00FH,0FCH,00FH,0FFH

21: DB 030H,000H,030H,003H,030H,00CH,030H,00FH

22: DB 030H,030H,030H,033H,030H,03CH,030H,03FH

23: DB 030H,0C0H,030H,0C3H,030H,0CCH,030H,0CFH

24: DB 030H,0F0H,030H,0F3H,030H,0FCH,030H,0FFH

25: DB 033H,000H,033H,003H,033H,00CH,033H,00FH

26: DB 033H,030H,033H,033H,033H,03CH,033H,03FH

27: DB 033H,0C0H,033H,0C3H,033H,0CCH,033H,0CFH

28: DB 033H,0F0H,033H,0F3H,033H,0FCH,033H,0FFH

29: DB 03CH,000H,03CH,003H,03CH,00CH,03CH,00FH

30: DB 03CH,030H,03CH,033H,03CH,03CH,03CH,03FH

31: DB 03CH,0C0H,03CH,0C3H,03CH,0CCH,03CH,0CFH

32: DB 03CH,0F0H,03CH,0F3H,03CH,0FCH,03CH,0FFH

33: DB 03FH,000H,03FH,003H,03FH,00CH,03FH,00FH

34: DB 03FH,030H,03FH,033H,03FH,03CH,03FH,03FH

35: DB 03FH,0C0H,03FH,0C3H,03FH,0CCH,03FH,0CFH

36: DB 03FH,0F0H,03FH,0F3H,03FH,0FCH,03FH,0FFH

37: DB 0C0H,000H,0C0H,003H,0C0H,00CH,0C0H,00FH

38: DB 0C0H,030H,0C0H,033H,0C0H,03CH,0C0H,03FH

39: DB 0C0H,0C0H,0C3H,0C0H,0CCH,0C0H,0CFH,0C0H

40: DB 0C0H,0F0H,0C0H,0F3H,0C0H,0FCH,0C0H,0FFH

41: DB 0C3H,000H,0CH3,003H,0C3H,00CH,0C3H,00FH

42: DB 0C3H,030H,0C3H,033H,0C3H,03CH,0C3H,03FH

43: DB 0C3H,0C0H,0C3H,0C3H,0C3H,0CCH,0C3H,0CFH

44: DB 0C3H,0F0H,0C3H,0F3H,0C3H,0FCH,0C3H,0FFH

45: DB 0CCH,000H,0CCH,003H,0CCH,00CH,0CCH,00FH

46: DB 0CCH,030H,0CCH,033H,0CCH,03CH,0CCH,03FH

47: DB 0CCH,0C0H,0CCH,0C3H,0CCH,0CCH,0CCH,0CFH

48: DB 0CCH,0F0H,0CCH,0F3H,0CCH,0FCH,0CCH,0FFH

49: DB 0CFH,000H,0CFH,003H,0CFH,00CH,0CFH,00FH

50: DB 0CFH,030H,0CFH,033H,0CFH,03CH,0CFH,03FH

51: DB 0CFH,0C0H,0CFH,0C3H,0CFH,0CCH,0CFH,0CFH

52: DB 0CFH,0F0H,0CFH,0F3H,0CFH,0FCH,0CFH,0FFH

53: DB 0F0H,000H,0F0H,003H,0F0H,00CH,0F0H,00FH

54: DB 0F0H,030H,0F0H,033H,0F0H,03CH,0F0H,03FH

55: DB 0F0H,0C0H,0F0H,0C3H,0F0H,0CCH,0F0H,0CFH

56: DB 0F0H,0F0H,0F0H,0F3H,0F0H,0FCH,0F0H,0FFH

57: DB 0F3H,000H,0F3H,003H,0F3H,00CH,0F3H,00FH

58: DB 0F3H,030H,0F3H,033H,0F3H,03CH,0F3H,03FH

59: DB 0F3H,0C0H,0F3H,0C3H,0F3H,0CCH,0F3H,0CFH

60: DB 0F3H,0F0H,0F3H,0F3H,0F3H,0FCH,0F3H,0FFH

61: DB 0FCH,000H,0FCH,003H,0FCH,00CH,0FCH,00FH

62: DB 0FCH,030H,0FCH,033H,0FCH,03CH,0FCH,03FH

63: DB 0FCH,0C0H,0FCH,0C3H,0FCH,0CCH,0FCH,0CFH

64: DB 0FCH,0F0H,0FCH,0F3H,0FCH,0FCH,0FCH,0FFH

65: DB 0FFH,000H,0FFH,003H,0FFH,00CH,0FFH,00FH

66: DB 0FFH,030H,0FFH,033H,0FFH,03CH,0FFH,03FH

67: DB 0FFH,0C0H,0FFH,0C3H,0FFH,0CCH,0FFH,0CFH

68: DB 0FFH,0F0H,0FFH,0F3H,0FFH,0FCH,0FFH,0FFH

69: CG ENDS

70: END START

本程式因为加了个转换表,空间增大为1471字元,但速度却加快为2.5 秒,这是空间换时间的最佳例证。

二、C

C近来极受美国各系统公司的推崇,我们特以之与组合语言作个比较,但不幸的是在指令的精简上,就显得力不从心,不像组合语言那样可以斤斤计较。

因此,我们只能就点阵移位、查小表及查总表的方式,测试其效率。首先,利用查大表的方式如下:

1: main()

2: {

3: unsigned char s[24][3];

4: unsigned short tab[256], d[48][3], count;

5: register short i,j,k;

6:

7: for (count = 0; count < 10000; count++)

8: {

9: k = 0;

10: for (i = 0; i < 24; i++)

11: {

12: for (j = 0; j < 3; j++)

13: d[k][j] = d[k + 1][j] = tab[s[i][j]];

14: k += 2;

15: }

16: }

17: }

程式制作时间10分钟,较组合语言稍快;占用空间4575字元,则大了三倍,至于执行速度为18秒,慢了七倍之多。

再换个方法,试一试查小表如次:

1: main()

2: {

3: unsigned char i,j, s[24][3], d[48][6], tab[16];

4: unsigned short count;

5: register short k, l, x;

6:

7: for (count = 0; count < 10000; count++)

8: {

9: k = 0;

10: for (i = 0; i < 24; i++)

11: {

12: l = 0;

13 for (j = 0; j < 3; j++)

14: {

15: x = s[i][j];

16: d[k][l] = d[k + 1][l] = tab[x & 0360 >> 4];

17: d[k][l+1] = d[k + 1][l + 1] = tab[x & 017];

18: l += 2;

19: }

20: k += 2;

21: }

22: }

23: }

占用空间为4,693 字元,比组合语言大了五倍;速度为30秒,则慢了四倍多。这证明了组合语言的灵活性,在空时效率交换的技术运用下,可以选择最有利的条件。再看利用位置的方式,结果如何?

1: main()

2: {

3: unsigned char ss[24][3];

4: unsigned short dd[48][3];

5: int i, k, count;

6: register short d, j;

7: register unsigned char s;

8:

9: for (count = 0; count < 10000; count++)

10: {

11: k = 0;

12: for (i = 0; i < 24; i++)

13: {

14: for (j = 0; j < 3; j++)

15: {

16: s = ss[i][j];

17: d = 0;

18: if (s & 01)

19: d |= 03;

20: if (s & 02)

21: d |= 014;

22: if (s & 04)

23: d |= 060;

24: if (s & 010)

25: d |= 0300;

26: if (s & 020)

27: d |= 01400;

28: if (s & 040)

29: d |= 06000;

30: if (s & 0100)

31: d |= 030000;

32: if (s & 0200)

33: d |= 0140000;

34: dd[k + 1][j] = dd[k][j] = d;

35: }

36: k += 2;

37: }

38: }

39:}

占用的空间为 4,727字元,较组合语言大四倍,执行时间29秒,差不多是四倍的差异。这种采用高阶指令的方式,拉近了C与组合语言的距离。足证纵然使用组合语言,若不采用精简指令的技巧,其效率不彰。一般程式师很少在组合语言的技巧上下功夫, 以致不能认识组合语言的真面目。

三、BASIC

10: DIM wd24(23,2),WD48(47,5),table(255),mask(7)

20: r1=0

30: r2=0

40: REM 用测试点的方式,每字元分八次处理。

50: mask(0)=0

60: mask(1)=2

70: FOR i=2 TO 7

80: mask(i)=mask(i-1)*2

90: NEXT i

100: INPUT A$

110: FOR count=1 TO 10

120: K=0

130: FOR i=O TO 23

140: T=0

150: FOR j=0 TO 2

160: FOR m=0 TO 7

170: temp=table(wd24(i,j))

180: temp=temp AND mask(m)

190: IF temp=128 THEN r1=192 AND r1

200: IF temp=64 THEN r1=48 AND r1

210: IF temp=32 THEN r1=12 AND r1

220: IF temp=16 THEN r1=3 AND r1

230: IF temp=8 THEN r2=192 AND r2

240: IF temp=128 THEN r2=48 AND r2

250: IF temp=64 THEN r2=12 AND r2

260: IF temp=32 THEN r2=3 AND r2

270: NEXT m

280: wd48(K,T)=r1

290: wd48(K,T+1)=r2

300: wd48(K+1,T)=r1

310: wd48(K+1,T+1)=r2

320: T=T+2

330: NEXT j

340: K=K+2

350: NEXT i

360: NEXT count

370: PRINT "FINISHED"

380: END

本程式制作时间为10分钟,执行程式共占12,764字元,执行时间为23,000秒!

足证BASIC 不适用于点阵处理,由于上述的处理方法是以移位为主,因BASIC 没有专用的指令,所以非常不利。现在改用查表方法,再看如何。

10: REM 本程式将24*24的点阵以查表方式转为48*48

20: REM 本程式用QuickBasic Version 4.00 Microsoft inc.

30: DIM WD24(23,2),WD48(47,2).TABLE(255)

40: FOR K=1 TO 100

50: T=0

60: FOR I=0 TO 23

70: FOR J=0 TO 2

80: A=TABLE(WD24(I,J))

90: WD48(T,J)=A

100: WD48(T+1,J)=A

110: NEXT J

120: NEXT I

130: NEXT K

140: END

本程式所用对照表与一、同,执行程式占11,642字元,执行时间共计1,800 秒。

其他的改进方法当然还有,可是看来已接近极限。

四、PASCAL

PASCAL仅适用于查总表的方式,在我们没有发展出「制表法」以前,几乎要放弃这个试验。现在,且沿用组合语言所用的总表,看其效率如何吧!

1: PROGRAM PASTABLE;

2: VAR

3: SOURCE :PACKED ARRAY[1…24,1…3] OF -128…127;

4: OBJCT :ARRAY[1…48,1…3] OF INTEGER;

5: TABLE :ARRAY[0255] OF INTEGER;

6: I,J,K,N:INTEGER;

7: BEGIN

8: FOR N:=1 TO 10000 DO

9: BEGIN

10: K:=O;

11: FOR I:=1 TO 24 DO

12: BEGIN

13: FOR J:=1 TO 3 DO

14: BEGIN

15: OBJCT[K,J]=TABLE[SOURCE[I,J];

16: OBJCT[K+1,J]=OBJCT[K,J]

17: END;

18: K:=K+2

19: END

20: END

21: END.

本程式制作需时10分钟,空间占11,650字元,执行时间为17秒,较BASIC 为佳。

显然 PASCAL 的效率较C及组合语言为差,但若不计总表,程式仅21条,差强人意。

五、FORTRAN

同样的,FORTRAN 也只能用查表的方法,程式如下:

1: DIMENSION IT1(24,3(,IT2(48,6),IT3(256)

2: DO 40 II=1,10000

3: DO 30 I=1,24

4: M=I+I

5: DO 30 J=1,3

6: K=IT3(IT1(I,J))

7: IT2(M-1,J)=K

8: 30 IT2(M,J)=K

9: 40 CONTINUE

10: END

这段程式也是用查表的方式,制作时间7分钟,执行程式 9,959字元,比C稍大,执行速度也较慢,为20秒。另外,在 FORTRAN中也没有找到适合的位元控制指令,因此很难再加改进。

从上述的试验中,可以看出这几种语言的效率差异。不论用什么方法,组合语言明显地遥遥领先。

就制作时间而言,因为程式简单,看不出很大分别。事实上,组合语言的确比较复杂,只是我们习惯成自然,有了经验,所以制作时显得轻松。

以下为上述测试的统计表:

┌────┬────┬────┬──────┬─────┬──────┐

│处理方式│程式语言│制作时间│ 程式空间 │执行速度 │ 备 注 │

│ │ │(分钟)│ (字元) │ (秒) │ │

├────┼────┼────┼──────┼─────┼──────┤

│点阵位移│组合语言│ 15 │ 970 │ 7.1 │ │

│ │C │ 10 │ 4,727 │ 29.0 │ │

│ │BASIC□│ 10 │ 12,764 │ 23,000.0 │ │

├────┼────┼────┼──────┼─────┼──────┤

│查小表法│组合语言│ 15 │ 949 │ 3.2 │边际效益最高│

│ │C │ 10 │ 4,693 │ 30.0 │ │

├────┼────┼────┼──────┼─────┼──────┤

│查总表法│组合语言│ 15 │ 1,441 │ 2.5 │速度效益最高│

│ │C │ 10 │ 4,575 │ 18.0 │ │

│ │PASCAL │ 10 │ 11,650 │ 17.0 │ │

│ │FORTRCN │□7 │ 9,959 │ 20.0 │ │

│ │BASIC │ 10 │ 11,692 │ 1,800.0 │ │

└────┴────┴────┴──────┴─────┴──────┘

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有