glider 发表于 2015-6-30 00:03:54

实验10第一个程序解题思路,欢迎交流

本帖最后由 glider 于 2015-6-30 00:09 编辑

这个问题实质上很简单,只要把需求搞清楚,转化为思路,剩下的就是写代码和调试代码了。
我们先看题目的要求,有2个:
      1. 读取data段中的字符,设置样式
      2. 把设置好样式的字符,写入到指定位置的显存中
那么我们的初步思路就应该是这样的:
      第一步,读取数据。读取data段中的数据,遇到0表示字符结束,这个应该不用再说了吧。
      第二步,处理数据,即设置样式。添加了显示样式的数据占两个字节,所以在第一步中,我们最好把数据读到一个reg的低位中,然后在这一步里,把样式(在cl中)写入到reg的高位。这一步也没有什么难点。
      第三步,写入显存。这是最关键的一步。把reg的内容显示在(dh)行、(dl)列,这个位置对应的内存地址,还需要我们自己去计算出来。显存所在的位置,实验9的题目介绍中已经详细说明了,这里不再缀述。
再要看上面的思路,读取数据、处理数据、写入数据可以放在一起,但是计算显示的位置,最好是单独拿出来,这样我们需要至少2个子程序:计算显示位置、把数据处理后显示出来;另外,主程序必不可少,它是整个程序的入口。我通常的写法是这样的:
      main:      主程序,初始化参数
                        
                        调用子程序sub1……
                        调用子程序sub2……
                        ……
                        
                        mov ax, 4c00h
                        int 21h

      sub1:      子程序1
      sub2:      子程序2
      ……


这个题目也不例外,看代码:assume cs:code
data segment
      db 'welcome to masm!', 0
data ends
code segment
       main:                           ;参数初始化
               mov dh, 8            ;字符显示在哪一行
               mov dl, 3               ;字符显示在哪一列
               mov cl, 2               ;字符的样式
               mov ax, data         ;初始化数据段地址,数据地址用ds:表示
               mov ds, ax
               mov si, 0      
               mov ax, 0b800h    ;初始化显示位置的段地址,显示地址用es:表示
               mov es, ax

               call show_str         ;调用在指定位置显示指定样式字符的方法

               mov ax, 4c00h      
               int 21h

      show_str:                      ;方法:在指定位置显示指定样式的字符
            call addr               ;调用方法:计算字符应该在哪个地址显示参数1:行号dh,参数2:列号dl,计算结果存储在bx中
            call show            ;调用方法:将字符显示在计算好的位置参数1:字符原地址ds:,参数2:字符显示位置es:,参数3:字符样式cl
            ret
      
   show:push cx                ;方法:读取数据段中的每一个字符,设置样式后,写入到显存中显示出来;参数1:字符原地址ds:,参数2:字符显示位置es:,参数3:字符样式cl
                push ax               
                s:      mov ah, cl      ;先把字符的样式从cl转存到ah
                        mov cl,       ;判断数据段是否读到0,如果读到0,从当前方法中返回
                        mov ch, 0
                        jcxz ok
                        mov al, cl      ;把字符内容转存到al,这个时候ax中包含了字符的样式和内容
                        mov es:, ax      ;把字符内容和样式写入显存,显示到屏幕
                        inc si               
                        add bx, 2      
                        mov cl, ah      ;把字符样式还原回cl中
                        jmp s               
      ok:         pop ax               
                        pop cx
                        ret

      addr:      push ax                ;方法:计算字符应该在哪个地址显示; 参数1:行号dh,参数2:列号dl,计算结果存储在bx中
                push dx                ;计算方法:80(字)*2(byte/字)*行号dh(0~24) + 列号dl*2(byte/列)
                mov al, 160      
                mul dh               
                mov dh, 0      ;把dh置为0,(dx) = (dl),这时候dx就是列号,方便与ax相加
                add ax, dx      ;因为每列2字节,所以列号要加两次
                add ax, dx
                mov bx, ax      ;把计算好的字符显示位置的偏移地址,存到bx中
                pop dx
                pop ax
                ret

code ends
end main
上面是我今天写的程序,时间太晚,明天还要早起上班,就不再优化了,各位如果有更好的思路,或者更优的处理方式,欢迎交流。重要表情发三遍:lol::lol::lol:






fast 发表于 2015-6-30 13:54:29

{:1_1:}

康小泡 发表于 2015-6-30 14:15:04

点个赞

1012662902 发表于 2015-6-30 23:55:48

谢谢LZ分享
页: [1]
查看完整版本: 实验10第一个程序解题思路,欢迎交流