实验九

1. 补全程序t1.asm,完成在屏幕上输出内存单元中的十进制两位数 2. 补全程序t2.asm,完成在屏幕上输出data段定义的5个十进制两位数,数

 1 ; 在屏幕上输出内存单元中的十进制两位数
 2 assume cs:code, ds:data
 3 data segment
 4      db 12
 5      db ?,?   ; 前一个字节用于保存商,后一个字节用于保存余数
 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:[2],al    ; 补全代码,让商保存到data段注释中指定的单元
17       mov ds:[3],ah    ; 补全代码,让余数保存到data段注释中指定的单元
18 
19       mov ah,2
20       mov dl,ds:[2]    ; 补全代码,使得dl <-- data段中保存的商的字节单元数值
21       add dl,30h    ; 补全代码,使得dl中的数值转换为数字字符
22       int 21h
23 
24       mov ah,2
25       mov dl,ds:[3]     ; 补全代码,使得dl <-- data段中保存余数的字节单元数值
26       add dl,30h     ; 补全代码,使得dl中的数值转换为数字字符      
27       int 21h
28 
29       mov ax,4c00h
30       int 21h
31 code ends
32 end start

2. 补全程序t2.asm,完成在屏幕上输出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       
10       mov cx,5
11       mov bx,0
12       
13       
14 s:    mov ah,0
15       mov al,ds:[bx]
16       mov dl,10
17       div dl
18       
19       mov ds:[5],al
20       mov ds:[6],ah
21       inc bx
22       
23       mov ah,2
24       mov dl,ds:[5]
25       add dl,30h
26       int 21h
27       
28       mov ah,2
29       mov dl,ds:[6]
30       add dl,30h
31       int 21h 
32       
33       mov ah,2
34       mov dl,0
35       int 21h 
36       loop s
37       ; 补全程序,参考t1.asm,综合应用以下知识完成:
38       ; (1) loop指令、内存单元地址的灵活表示
39       ; (2) div指令, 数字→数字字符的转换
40       ; (3) int 21h的2号子功能,完成单个字符输出的方法,即: 
41       ;     mov ah,2
42       ;     mov dl,待输出字符或其ASCⅡ码
43       ;     int 21h
44       ; (4) 数据和数据之间以空格间隔的实现: 使用(3)输出空格字符
45       
46       mov ax,4c00h
47       int 21h
48 code ends
49 end start

3. 教材实验9(P187)

 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 
 9 code segment
10 start:  mov ax,data
11         mov ds,ax            ;字符串及属性值所在段的段地址送入ds
12         
13         mov ax,0b800H
14        
15         mov es,ax            ;80×25彩色字符模式显示缓冲区段地址送入es
16         
17         mov si,0        ;用来记录属性
18         mov cx,3
19         
20 
21         mov di,0
22         mov di,0678h;相对于es:0的偏移量,要显示到屏幕中心,需要给一个初始的偏移量,di:目的变址寄存器
23 s:      push cx;外循环
24         mov byte ptr al,ds:[10h+si];存放属性
25         mov bx,0
26         mov cx,10h
27 
28 s1:     mov dl,ds:[bx]
29         mov byte ptr es:[di],dl
30         mov byte ptr es:[di+1],al
31         inc bx
32         add di,2
33         loop s1
34         
35         pop cx
36         
37         mov ax,es
38         add ax,8;到下一行去,一行80个字符,一个字符256种属性
39         mov es,ax
40         inc si
41         loop s
42         ; 添加代码,通过循环逐个将每个字符及其属性送入相应的显示缓冲区对应行
43         ; 即:将data段的字符及属性通过循环逐个mov到显示缓冲区(es)段相应的单元内
44         
45         ; 可以先尝试分别写三段代码,每次完成一行的显示
46         ; 程序运行起来后,再尝试通过灵活的寻址方式和循环,对三段代码修改和简化
47         ; 学习第10章子程序后,还可以进一步完善优化,设计子程序,将行号、列号、颜色属性设置成入口参数
48         
49 
50         mov ax,4c00h
51         int 21h
52 code ends
53 end start

结果截图:

 总结与体会

最后一个实验感触较深,通过栈来储存CX的值,来实现二次循环。

由于不能像C语言中自由地申请内存空间,故只能调用栈机制。将需要使用的寄存器内的变量入栈,然后使用寄存器当一个新的变量,很显然,这样当你需要管理很多个变量的时候会带来极大的不方便。因为不能直接通过一次出栈来访问,而需要通过访问内存单元的方法,这是不安全的。(实模式下就不管安全了吧。。。

在最后一个实验中,我没有设置SS,SP的初始值,所以会有一个随机的初始值,会操作一块未知的内存单元,(这也是不安全的)不知道会不会出问题

 对于显存空间:B8000H-BFFFFH   25行*80个字符,每个字符256种属性。

最后转载一下寄存器的英文名,方便读者记忆(明明是自己实验时记错好几次。。)(如何充分安排寄存器的使用还真是个问题,目前程序短还好,长的话就。。。

1:数据寄存器,一般称之为通用寄存器组

     8086 有8个8位数据寄存器,
     这些8位寄存器可分别组成16位寄存器:
     AH&AL=AX:累加寄存器,常用于运算;
     BH&BL=BX:基址寄存器,常用于地址索引;
     CH&CL=CX:计数寄存器,常用于计数;
     DH&DL=DX:数据寄存器,常用于数据传递。

   2:地址寄存器/段地址寄存器

     为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:
     CS(Code Segment):代码段寄存器;
     DS(Data Segment):数据段寄存器;
     SS(Stack Segment):堆栈段寄存器;
     ES(Extra Segment):附加段寄存器。

3:特殊功能的寄存器

     IP(Instruction Pointer):指令指针寄存器,与CS配合使用,可跟踪程序的执行过程;
     SP(Stack Pointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置。
     BP(Base Pointer):基址指针寄存器,可用作SS的一个相对基址位置;
     SI(Source Index):源变址寄存器可用来存放相对于DS段之源变址指针;
     DI(Destination Index):目的变址寄存器,可用来存放相对于 ES 段之目的变址指针。

来源:http://nannan408.iteye.com/blog/982942

 关于中断,可以参考:https://blog.csdn.net/heavengl/article/details/6035716

原文地址:https://www.cnblogs.com/asm085/p/10061693.html