菜鸟与你分享如何写程序
    如何写程序是个很深的话题,不敢妄加臆断.在这里只想通过一个小程序与大家分享一下心得,纯属个人经验,不足之处还请老鸟斧正.
    相信很多和我一样的朋友曾经有这样的困惑,看书上的例子都懂,课后习题也大概的懂.或者看着书上的例子也能敲出一点东西来,但是一离
 开书本基本就没什么头绪了.感觉想写什么都无从下手,学了那么长时间那么多东西感觉无一点用处.于是乎,很苦恼的坐在电脑前发呆,看看网页
 ,玩玩游戏,慢慢的时间混过去了...
    首先我们要明白一点,程序是为了解决问题的.而解决问题就需要工具,语言就是写程序的工具,仅仅是个工具.一定要确定语言的地位,战略上藐视它,实践中重视它.
有些初学者被语言奴役了,学完这个学那个,整天被不同语言的语法区别搞的晕头转向.要意识到我们才是主人,语言才是奴隶.我们让它做什么,它就要不停的做,直到收到停止指令.
    编程重要的是思想.一个问题出来后,我们要想到怎么去解决它,然后用语言实现就好了.好了,废话说多了.举个简单的例子,王爽汇编书中的一个实验题,相信很多人看过或者正在看或者即将要看.
    题目:
                            '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
    这时候看一下字符串,字母开始的位置并不是第1位而是地4位.那就加3吧(为什么加3?这个...幼儿园有的教.)
代码:
            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
   这里又有个问题了,第一次执行到loop s结束后cx已经变成0了,然后到 loop s0时候由于cx已经是0所以行数循环一次就退出了.
  这时候肯定有聪明的朋友说这个简单,由于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
          哎呀,这里大功告成了.你看编程多简单.你看我们每行的前4个字符变大写了吧.
          我们都知道[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
  编译一下吧,debug载入,看看是不是前4个字母大写了.
  终于好了,一看表.哎呀,2小时过去了.不禁有人要想了,我2小时才写了这么个破程序.大多数人说不定几分钟,几秒钟就搞定了.
  这个吗,不能心急啊.慢慢来啊,你也会越来越熟练的.毕竟2小时你还憋出个东西来吗.大爷们不都是从孙子走过来的么?
  真的没有看着书就写出来了
  这个可以有,
  这个没有.
  这个真的可以有,
  这个真的没有.
  程序本身很简单,操作数组而已.关键是整个程序怎么写出来的,希望能对离开书就无从下手的朋友有点帮助.
  想到什么就用你所熟悉的语言写出来,不要怕错,怕自己写出来的不好,只要能解决问题就行,管它怎么实现呢.
  况且世上本来就没什么绝对的对和错,都是万恶的应试制度灌输的非对及错,非正及负,非生即死....
  打住,我承认鸡冻了.没想到我还是个愤青啊,防止被跨省...嘘...嘘...
  有时候想到的东西程序语言表达不出来也没关系,先画出来也好,只要自己能看明白思路.然后再查语法啊,api什么的实现.
  要敢想,大胆的去思考,不要被任何东西束缚你的思想.思想比知识更重要,这句话谁说的来着?呵呵,太熟悉了吧.
  菜鸟的感想,难免有不足之处.欢迎各位指正交流.