鱼C论坛

 找回密码
 立即注册
查看: 3159|回复: 6

[争议讨论] 有关子程序功能设计的问题

[复制链接]
发表于 2011-7-4 12:10:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 linha0 于 2011-7-5 17:41 编辑

一个子程序的功能:
1、应该是尽量的细化好呢?
2、还是尽量宏观化好呢?(不知怎么样形容,只好用宏观)

比如,转化大小写的功能:
用子程序来表示


1、用单个字母做参数,然后在子程序中转化,并返回结果;


2、不论要转化的是字母还是字符串,一律当作字符串处理;

具体实现:
参数(起始地址,字符串长度,字符串地址),然后在子程序中直接转化字符串,不用返回



这应该怎么选择好呢?
是具体问题,具体选择
还是,所有问题统一解决



想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2011-7-4 13:13:38 | 显示全部楼层
回答这个问题前,还是要思考下子程序的作用.把功能重复的代码拿出来,以便重复利用
如果楼主的这两个子程序都可以实现这个目的,那用哪种都可以了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2011-7-4 16:08:06 | 显示全部楼层
大概因为之前有学过一点微软的编程知识,但又因为学得不好,所以就有点“断章取义”地造成了前面 的那 两个 问题;

下面就第十章的10.11和10.12两个例题来说:
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2011-7-4 16:27:03 | 显示全部楼层
本帖最后由 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,[si]
                call uppercase                ;调用子程序1
                mov [si],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,[si]
                and al,11011111b
                mov [si],al
                inc si
                loop uppercase2
                ret

2、这样解决了子程序1的代码可重用性的问题了。但是在接下来的10.12中,需要把子程序2的功能改造成另一种相似的功能。子程序3:
uppercase3:        
                mov cl,[si]
                mov ch,0
                jcxz ok;不需要在子程序外面再设置CX的值
                
                and cl,11011111b
                mov [si],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,[si]
            call uppercase;调用子程序1
            mov [si],al
            inc si
            loop uppercase2
            ret

uppercase3:
            mov cl,[si]
            mov ch,0
            jcxz ok;不需要在子程序外面再设置CX的值

                        mov al,cl
            call uppercase;调用子程序1
            mov [si],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 [si],11011111b
            ret

uppercase2:
            call uppercase;调用子程序1
            inc si
            loop uppercase2
            ret

uppercase3:
            mov cl,[si]
            mov ch,0
            jcxz ok;不需要在子程序外面再设置CX的值

            call uppercase;调用子程序1
            inc si
                        jmp short uppercase3

        ok:        ret
code ends
end start

6、再次删掉一些碍眼的东东后,这下爽快了。可是,我回头一看,于是彻底的{:2_36:}………………
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2011-7-4 17:53:29 | 显示全部楼层
最终,问题又回到了起点。

子程序的功能设计,要怎么去设计呢?

要怎样去保证代码的可重用性?

要不要给代码留下可以扩展的可能呢?

要不要形成自己的一套编程习惯呢?(按中国的说法:叫套路;按老外的说法:叫框架)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2011-7-5 05:48:34 | 显示全部楼层
比如,转化大小写的功能:
用子程序来表示


1、用单个字母做参数,然后在子程序中转化,并返回结果;

我觉得,具体情况具体分析。任何时候设计程序都要考虑两个方面:最恶劣的计算机环境(例如256MB内存……)和用户的真实体验。每转换一个字母调用一次子程序的确规范,但消耗内存比较严重,不推荐。

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
 楼主| 发表于 2011-7-5 17:38:26 | 显示全部楼层
本帖最后由 linha0 于 2011-7-5 17:44 编辑

我也觉得呢!不过回过头来,再重新整理一下思路,发现:and al,11011111b     这个指令功能已经是最小的核心单元了。我竟然还跑去封装它,这简直就是吃饱撑着了的:lol

不过我还是有个疑问,子程序的调用过程如下(俺的理解):
1、执行Call指令,入栈并跳转到子程序内存段。(这时占有栈段一小部份内存空间

2、执行子程序的相应代码指令。(程序加载时就已经占有的内存空间

3、执行Ret指令,出栈并返回主程序。(同时还原已占有的栈段空间

按这样的理解,调用子程序时占用的内存空间并不会增加多少才对。但是,如果调用子程序的频率过高的话,消耗的应该是CPU资源吧?

我也不知道这样分析对不对,请指正!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-19 01:41

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表