有关子程序功能设计的问题
本帖最后由 linha0 于 2011-7-5 17:41 编辑一个子程序的功能:
1、应该是尽量的细化好呢?
2、还是尽量宏观化好呢?(不知怎么样形容,只好用宏观)
比如,转化大小写的功能:
用子程序来表示
1、用单个字母做参数,然后在子程序中转化,并返回结果;
2、不论要转化的是字母还是字符串,一律当作字符串处理;
具体实现:
参数(起始地址,字符串长度,字符串地址),然后在子程序中直接转化字符串,不用返回
这应该怎么选择好呢?
是具体问题,具体选择
还是,所有问题统一解决
回答这个问题前,还是要思考下子程序的作用.把功能重复的代码拿出来,以便重复利用
如果楼主的这两个子程序都可以实现这个目的,那用哪种都可以了 大概因为之前有学过一点微软的编程知识,但又因为学得不好,所以就有点“断章取义”地造成了前面 的那 两个 问题;
下面就第十章的10.11和10.12两个例题来说: 本帖最后由 linha0 于 2011-7-4 17:45 编辑
在做10.11的时候,程序是这样设计的:
assume cs:code,ds:data
data segment
db 'conversation',0
data ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0
mov cx,12
s: mov al,
call uppercase ;调用子程序1
mov ,al
inc si
loop s
mov ax,4c00h
int 21h
uppercase: ;子程序1:利用AL保存参数,然后在子程序中转化,最后返回AL
and al,11011111b
ret
code ends
end start
1、最先是以功能最小化为目的,但是这样做,每次调用子程序1都需要重写一段循环的指令。感觉太麻烦了,于是就用子程序2来代替子程序1:
uppercase2:
mov al,
and al,11011111b
mov ,al
inc si
loop uppercase2
ret
2、这样解决了子程序1的代码可重用性的问题了。但是在接下来的10.12中,需要把子程序2的功能改造成另一种相似的功能。子程序3:
uppercase3:
mov cl,
mov ch,0
jcxz ok;不需要在子程序外面再设置CX的值
and cl,11011111b
mov ,cl
inc si
ok: ret
3、如果还需要再改造一个相似功能的子程序;又或者,在复制“and cl,11011111b” 这类功能相同代码相似的指令时出了错,会很麻烦的。如果这种子程序再多一些呢?
4、于是,就有了最终版程序代码(这让我想起了我的一个想当年的同事)
assume cs:code,ds:data
data segment
db 'conversation',0
data ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0
mov cx,12
call uppercase2;调用子程序2,10.11题
mov ax,4c00h
int 21h
uppercase: ;子程序1:利用AL保存参数,然后在子程序中转化,最后返回AL
and al,11011111b
ret
uppercase2:
mov al,
call uppercase;调用子程序1
mov ,al
inc si
loop uppercase2
ret
uppercase3:
mov cl,
mov ch,0
jcxz ok;不需要在子程序外面再设置CX的值
mov al,cl
call uppercase;调用子程序1
mov ,al
inc si
jmp short uppercase3
ok: ret
code ends
end start
5、可是,这个代码怎么看怎么不爽。于是,又学我的同事在后面再加上“完美”两个字,最终完善版(搞笑一下):assume cs:code,ds:data
data segment
db 'conversation',0
data ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0
mov cx,12
call uppercase2;调用子程序2,10.11题
mov ax,4c00h
int 21h
uppercase: ;子程序1:利用AL保存参数,然后在子程序中转化,最后返回AL
and byte ptr ,11011111b
ret
uppercase2:
call uppercase;调用子程序1
inc si
loop uppercase2
ret
uppercase3:
mov cl,
mov ch,0
jcxz ok;不需要在子程序外面再设置CX的值
call uppercase;调用子程序1
inc si
jmp short uppercase3
ok: ret
code ends
end start
6、再次删掉一些碍眼的东东后,这下爽快了。可是,我回头一看,于是彻底的{:2_36:}………………
最终,问题又回到了起点。
子程序的功能设计,要怎么去设计呢?
要怎样去保证代码的可重用性?
要不要给代码留下可以扩展的可能呢?
要不要形成自己的一套编程习惯呢?(按中国的说法:叫套路;按老外的说法:叫框架) 比如,转化大小写的功能:
用子程序来表示
1、用单个字母做参数,然后在子程序中转化,并返回结果;
我觉得,具体情况具体分析。任何时候设计程序都要考虑两个方面:最恶劣的计算机环境(例如256MB内存……)和用户的真实体验。每转换一个字母调用一次子程序的确规范,但消耗内存比较严重,不推荐。
本帖最后由 linha0 于 2011-7-5 17:44 编辑
我也觉得呢!不过回过头来,再重新整理一下思路,发现:and al,11011111b 这个指令功能已经是最小的核心单元了。我竟然还跑去封装它,这简直就是吃饱撑着了的:lol
不过我还是有个疑问,子程序的调用过程如下(俺的理解):
1、执行Call指令,入栈并跳转到子程序内存段。(这时占有栈段一小部份内存空间)
2、执行子程序的相应代码指令。(程序加载时就已经占有的内存空间)
3、执行Ret指令,出栈并返回主程序。(同时还原已占有的栈段空间)
按这样的理解,调用子程序时占用的内存空间并不会增加多少才对。但是,如果调用子程序的频率过高的话,消耗的应该是CPU资源吧?
我也不知道这样分析对不对,请指正!
页:
[1]