实验九 根据材料编程

练习1:

  在屏幕上输出内存单元中的十进制两位数。

 1 ; 在屏幕上输出内存单元中的十进制两位数
 2 assume cs:code, ds:data
 3 data segment
 4      db 12
 5      db 0,0   ; 前一个字节用于保存商,后一个字节用于保存余数
 6 data ends
 7 code segment
 8 start:
 9       mov ax,data
10       mov ds,ax        ; 补全指令,使得ds <-- data段地址
11       
12       mov ah,0
13       mov al,ds:[0]   ; ax <-- data段字节单元的被除数12
14       mov bl,10
15       div bl
16       mov  ds:[1],al    ; 补全代码,让商保存到data段注释中指定的单元
17       mov  ds:[2],ah    ; 补全代码,让余数保存到data段注释中指定的单元
18 
19       mov ah,2
20       mov dl,ds:[1]    ; 补全代码,使得dl <-- data段中保存的商的字节单元数值
21       add dl,30H       ; 补全代码,使得dl中的数值转换为数字字符
22       int 21h
23 
24       mov ah,2
25       mov dl,ds:[2]     ; 补全代码,使得dl <-- data段中保存余数的字节单元数值
26       add dl,30H        ; 补全代码,使得dl中的数值转换为数字字符      
27       int 21h
28 
29       mov ax,4c00h
30       int 21h
31 code ends
32 end start
View Code

  现在所学,只能输出当个字符。

1 mov ah,2
2 mov dl,30H
3 int 21h

  dl是要输出的数值。

  现在的想法是一位一位输出,先通过除十,商为十位上的值,余数为个位数上的值。

  附除法(div)使用方法:

    (1)除数:有8位或者16位两位,在一个reg或内存单元中。

    (2)被除数:默认放在AX或者DX中,如果除数为8位,被除数则为16位,默认在AX中存放;如果除数为16位,被除数则为32位,在DX和AX中存放,DX存放高16位,AX存放低16位。

    (3)结果:如果除数为8位,则AL存储除法操作的商,AH存储除法操作的余数;如果除数为16位,则AX存储除法操作的商,DX存储除法操作的余数。

练习2:

  在屏幕上输出data段定义的5个十进制两位数,数据和数据之间以空格间隔。 

 1 assume cs:code, ds:data
 2 data segment
 3      db 12,35,96,55,67
 4 data ends
 5 code segment
 6 start:
 7       mov ax,data
 8       mov ds,ax
 9       mov cx,5
10       mov bx,0
11 s:    mov ax,0
12       mov dl,10
13       mov al,[bx]
14       div dl
15       mov dl,al
16       mov dh,ah
17 
18       mov ah,2
19       add dl,30H
20       int 21H
21 
22       mov ah,2
23       mov dl,dh
24       add dl,30H
25       int 21H
26 
27       mov ah,2
28       mov dl,20H
29       int 21H 
30       inc bx
31       loop s
32       
33       mov ax,4c00h
34       int 21h
35 code ends
36 end start
View Code

  思路同第一问,先将data作为段地址,之后将数据读入al中,用除法,取每一位的个数,输出。

  空格的ASCII码为20H。

  

 练习3:

  编程:在屏幕中间分别显示绿色、绿色红底、白色蓝色的字符串'Welcome to masm!'

 1 ; p187 实验9
 2 
 3 assume ds:data, cs:code
 4 data segment
 5        db 'Welcome to masm!'  
 6        db 2H,24H,71H          ;字符串属性值
 7 data ends
 8 code segment
 9 start:  mov ax,data
10         mov ds,ax            ;字符串及属性值所在段的段地址送入ds
11         mov ax,0b800H
12         mov es,ax            ;80×25彩色字符模式显示缓冲区段地址送入es
13         mov si,06E0H      ;es的偏移地址
14         mov bx,0             ;属性值的偏移地址
15         mov cx,3
16 
17 k:     mov dh,cl
18         mov cx,16
19         mov di,0
20 z:      mov al,ds:[di]
21         mov es:[si],al
22         inc si
23         mov al,ds:[bx+16]
24         mov es:[si],al 
25         inc di
26         inc si
27         loop z
28 
29         inc bx
30         mov cl,dh
31         add si,0080H
32         loop k
33 
34         mov ax,4c00h
35         int 21h
36 code ends
37 end start
View Code

  

  里面用了两重循环,第一层循环为3,第二层循环为16。loop用执行的时候当且仅当判断CX的值,所以我们可以先藏起来。偷偷地赋给BH值,再给CX赋第二层循环的次数,第二层循环完了,BH再找回并把CX的初值交给CX,并执行loop。(感觉自己可以去一篇小说了。。。)如果想要n重循环(n>2),建议创建栈空间,分别利用PUSH,POP实行上述操作。因为寄存器个数有限。需要合理运用。且行且珍惜。AX不断重写数据,CX判断循环,不能乱放数据。一下子少了两个能用的寄存器,所以正常能用也就是BX和DX了。。

  中间的行数是11,12,13行

    

  注意:其中换行,应该si+80H,而不是A0H,是因为第一次循环结束时,si=06E0H+20H=0700H,再加A0H,就变成了07A0H,而第二次开始的si应该是0780H,其中多加商第一次循环所的20H。

  全屏输出: 

 1 assume ds:data, cs:code
 2 data segment
 3        db 'Welcome to masm!'  
 4        db 2H,24H,71H          ;字符串属性值
 5 data ends
 6 code segment
 7 start:  mov ax,data
 8         mov ds,ax            ;字符串及属性值所在段的段地址送入ds
 9         mov ax,0b800H
10         mov es,ax            ;80×25彩色字符模式显示缓冲区段地址送入es
11         mov si,0              ;es的偏移地址
12         mov bx,0             ;属性值的偏移地址
13         mov cx,125
14 
15 k:     mov dh,cl
16         mov cx,16
17         mov di,0
18 z:      mov al,ds:[di]
19         mov es:[si],al
20         inc si
21         mov al,ds:[bx+16]
22         mov es:[si],al 
23         inc di
24         inc si
25         loop z
26 
27         inc bx
28         mov ax,bx
29         mov bx,3
30         div bl
31         mov bl,ah
32         mov cl,dh
33         loop k
34 
35         mov ax,4c00h
36         int 21h
37 code ends
38 end start
View Code

  其中比较重要的一个,就是多加一个bx取3的余数。

  运行结果:

   

 实验总结与感受

  1.输出方法,单个字符输出。其中dl是ASCII码。

    mov ah,2 

    mov dl,al

    int 21h

  2.第种输出方法是向B8000H-BFFFFH显示缓冲区,偶地址放入字符的ASCII码,奇地址存放字符的颜色属性。显示屏可以显示25行,每行80个字符,即B8000H~B8F9FH。

   颜色属性:R:红色      G:绿色       B:蓝色

  7 6 5 4 3 2 1 0
含义 BL R G B I R G B
  闪烁 背景 高亮 前景

  

  3.关于多重循环,loop只能判断CX的值,要多重循环时,就必须先把CX的值,藏起来,再给CX重新赋值。这个过程可以用栈来执行。如果循环次数少,则用寄存器来存。

原文地址:https://www.cnblogs.com/auspice/p/10059519.html