菜鸟与你分享如何写程序
如何写程序是个很深的话题,不敢妄加臆断.在这里只想通过一个小程序与大家分享一下心得,纯属个人经验,不足之处还请老鸟斧正.
相信很多和我一样的朋友曾经有这样的困惑,看书上的例子都懂,课后习题也大概的懂.或者看着书上的例子也能敲出一点东西来,但是一离
开书本基本就没什么头绪了.感觉想写什么都无从下手,学了那么长时间那么多东西感觉无一点用处.于是乎,很苦恼的坐在电脑前发呆,看看网页
,玩玩游戏,慢慢的时间混过去了...
首先我们要明白一点,程序是为了解决问题的.而解决问题就需要工具,语言就是写程序的工具,仅仅是个工具.一定要确定语言的地位,战略上藐视它,实践中重视它.
有些初学者被语言奴役了,学完这个学那个,整天被不同语言的语法区别搞的晕头转向.要意识到我们才是主人,语言才是奴隶.我们让它做什么,它就要不停的做,直到收到停止指令.
编程重要的是思想.一个问题出来后,我们要想到怎么去解决它,然后用语言实现就好了.好了,废话说多了.举个简单的例子,王爽汇编书中的一个实验题,相信很多人看过或者正在看或者即将要看.
题目:
'1. display '
'2. brows '
'3. replace '
'4. modify '
要求:将上面4个字符串前四个字母变成大写.
拿到题目后,我们开始糊涂了....
不急,这时候我们有可能只记得一个最重要的知识点就是 二进制ASCII码 和11011111B,与(and)一下就变成大写了.这点应该是看书后的绝大多数人记得的吧.有时候,确实我们能想到的就是一些解决问题的关键步骤,但是具体实现完全没头绪.没事,想到这里我们立刻转变成程序语句.
二进制ascii码 and 11011111B
到这里,自然的想到:哎呀,这样的东西,程序怎么能执行呢,管他呢,想到了就写出来吧.知道一点语法的知道,汇编不能识别(二进制ASCII码)这样的东西的.对了,汇编书不都是介绍了8086有很多寄存器么,既然是汇编给的那肯定能认识了吧.那就拿过来存放字符串吧,随便选个寄存器.就bx吧.
于是就变成:
and [bx],11011111B
问题又来了:and操作需要指明2个操作数的大小的,后面11011111B一看就知道是8位的.前面[bx]就需要我们指明了.其实这里不指明也不要紧,编译时,肯定出错一看提示就明白了.这也是我们经常遇到的这类情况,很正常的.我们还是指明下不用编译时候再回来改了.
and byte ptr [bx],11011111B ;指明[bx]"三维"是byte型的和后面的对应
好了,这里实现了一个字符的大写转换,那要实现4个呢.那就循环一下吧
我们希望bx从0变到3.那就每次循环加1吧,初始值设为0.
mov cx,4 ;先设置一下循环次数 mov bx,0 ;初始设为0,从第一个字母开始. s: and byte ptr [bx],11011111B inc bx ;每次循环+1,指向下个字母. loop s
mov cx,4 ;先设置一下循环次数 mov bx,0 ;初始设为0,从第一个字母开始. s: and byte ptr [bx+3],11011111B inc bx ;每次循环+1,指向下个字母. loop s
第一行前4个都变大写.有人要问:有4行呢,怎么办?头又要昏了.慢慢想,第一行前4个我都能变大写了,那把上面程序指向第2行再执行一次不就好了吗,第三第四也一样.这样一来4行只要外面再循环四次就好了.刚才已经用bx表示列数了,现在行循环又要个寄存器了.就选di表示行数.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov cx,4 ;4行循环4次 mov di,0 ;从第一行开始 s0: {每行变大写} add di,16 ;每次循环变到下一行.或者 add di,10h.每行大小是16个字节,不足的用空格填充的. loop s0
上面我们已经把每行变大写的代码写出来了,直接替换吧
mov cx,4 ;4行循环4次 mov di,0 ;从第一行开始 s0: mov cx,4 ;先设置一下循环次数 mov bx,0 ;初始设为0 s: and byte ptr [bx+3+di],11011111B inc bx ;每次循环+1,指向下个字母 loop s add di,16 ;每次循环变到下一行.或者 add di,10h.每行大小是16个字节 loop s0
这时候肯定有聪明的朋友说这个简单,由于cx用冲突了,反正寄存器多呢,把里面的cx换成dx什么的不就好了吗.这里人脑优点又体现了,本来我们想换成es,dx,甚至是奥特曼打小怪兽都可以的啊.只要存放下循环次数不和cx重复,就可以了吗.
对不起,汇编里循环次数只能用cx存储.也就是说loop 只认识 cx.那我们就要把第一个cx在s循环前转存下,然后s循环结束后再放出来了.
有2个方法:1.再选个寄存器,s循环结束后放回去.比如si, 2.放到堆栈里,s循环结束后出栈
1. mov cx,4 ;4行循环4次 mov di,0 ;从第一行开始 s0: mov si,cx ;用si存放上面的cx mov cx,4 ;先设置一下循环次数 mov bx,0 ;初始设为0 s: and byte ptr [bx+3+di],11011111B inc bx ;每次循环+1,指向下个字母 loop s mov cx,si ;存放的第一个cx值释放出来 add di,16 ;每次循环变到下一行.或者 add di,10h loop s0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2. mov cx,4 ;4行循环4次 mov di,0 ;从第一行开始 s0: push cx ;cx入栈保存 mov cx,4 ;先设置一下循环次数 mov bx,0 ;初始设为0 s: and byte ptr [bx+3+di],11011111B inc bx ;每次循环+1,指向下个字母 loop s pop cx ;cx出栈计数行号 add di,16 ;每次循环变到下一行.或者 add di,10h loop s0
我们都知道[bx]肯定是指向字符串首地址的啦,但是汇编很笨的.还需要我们告诉他.用到堆栈的还要告诉 汇编哪里是堆栈,哪里是代码段,程序从哪里开始.
1. assume cs:code,ds:data data segment db '1. display ' db '2. brows ' db '3. replace ' db '4. modify ' data ends code segment ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start: mov ax,data mov ds,ax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;把上面的拷贝过来,解决问题;;;;;;;;;;;;;;;;;;;;;;;; mov cx,4 ;4行循环4次 mov di,0 ;从第一行开始 s0: mov si,cx ;用si存放上面的cx mov cx,4 ;先设置一下循环次数 mov bx,0 ;初始设为0 s: and byte ptr [bx+3+di],11011111B inc bx ;每次循环+1,指向下个字母 loop s mov cx,si ;存放的第一个cx值释放出来 add di,16 ;每次循环变到下一行 loop s0 mov ax,4c00h ;程序返回 int 21h code ends end start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2. assume cs:code,ss:stack,ds:data stack segment dw 0,0,0,0,0,0,0,0 stack ends data segment db '1. display ' db '2. brows ' db '3. replace ' db '4. modify ' data ends code segment ;;;;;;;;;;;;;;;;;;;;;;;;;;;;指明数据段;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start: mov ax,data mov ds,ax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;指明堆栈;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov ax,stack mov ss,ax mov sp,10h ;指针指向栈底 ;;;;;;;;;;;;;;;;;;;;;;;;;;;循环开始;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov cx,4 mov di,0 s0: push cx mov cx,4 mov bx,0 s: and byte ptr[bx+3+di],11011111B inc bx loop s pop cx add di,16 loop s0 mov ax,4c00h ;程序返回 int 21h code ends end start
终于好了,一看表.哎呀,2小时过去了.不禁有人要想了,我2小时才写了这么个破程序.大多数人说不定几分钟,几秒钟就搞定了.
这个吗,不能心急啊.慢慢来啊,你也会越来越熟练的.毕竟2小时你还憋出个东西来吗.大爷们不都是从孙子走过来的么?
真的没有看着书就写出来了
这个可以有,
这个没有.
这个真的可以有,
这个真的没有.
程序本身很简单,操作数组而已.关键是整个程序怎么写出来的,希望能对离开书就无从下手的朋友有点帮助.
想到什么就用你所熟悉的语言写出来,不要怕错,怕自己写出来的不好,只要能解决问题就行,管它怎么实现呢.
况且世上本来就没什么绝对的对和错,都是万恶的应试制度灌输的非对及错,非正及负,非生即死....
打住,我承认鸡冻了.没想到我还是个愤青啊,防止被跨省...嘘...嘘...
有时候想到的东西程序语言表达不出来也没关系,先画出来也好,只要自己能看明白思路.然后再查语法啊,api什么的实现.
要敢想,大胆的去思考,不要被任何东西束缚你的思想.思想比知识更重要,这句话谁说的来着?呵呵,太熟悉了吧.
菜鸟的感想,难免有不足之处.欢迎各位指正交流.