1. 实验任务1
教材「实验9 根据材料编程」(P187-189)编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串‘welcome to masm!‘。
解题思路:根据学习的知识,我知道该页在显示缓冲区的位置从B8000H开始,要在屏幕中间,对照表格,我输出的三行应是11,12,13行。11行的起始地址为1760,我的输入内容占16bytes*2=32。(160-32)/2=64。所以我的初始地址偏移量是1760+64=1824,转换为十六进制是720h。B8000H+720H=B8720H,所以我把初始es设置为B872,这样偏移变量就从0开始。
编写代码的想法,内层循环控制每行输出字符,外层循环控制打印三行。
1 assume cs:code, ds:data, ss:stack 2 data segment 3 db ‘welcome to masm!‘ 4 db 2h,24h,71h ;颜色 5 data ends 6 stack segment stack 7 db 16 dup (0) 8 stack ends 9 10 code segment 11 start: 12 mov ax,data 13 mov ds,ax 14 mov ax,stack 15 mov ss,ax 16 mov sp,16 17 mov ax,0B872h 18 mov es,ax 19 mov cx,3 20 mov bx,16 21 s: 22 push cx 23 mov cx,16 24 mov si,0 25 mov di,0 26 s0: 27 mov al,ds:[di] 28 mov ah,ds:[bx] 29 mov es:[si],ax 30 add si,2 31 inc di 32 loop s0 33 34 pop cx 35 mov ax,es 36 add ax,000ah 37 mov es,ax 38 inc bx 39 loop s 40 41 mov ax,4c00h 42 int 21h 43 44 code ends 45 end start
实验代码运行结果:
2. 实验任务2
编写子程序printStr,实现以指定颜色在屏幕上输出字符串。调用它,完成字符串输出。
子程序printSar
功能:以指定颜色在屏幕上(从屏幕左上角开始)输出字符串要求:字符串以0结尾入口参数字符串的起始地址—> ds: si (其中,字符串所在段的段地址—> ds, 字符串起始地址的偏移地址—> si字符串颜色—> al出口参数:无
1 assume cs:code, ds:data 2 data segment 3 str db ‘try‘, 0 4 data ends 5 6 code segment 7 start: 8 mov ax, data 9 mov ds, ax 10 11 mov si, offset str 12 mov al, 2 13 call printStr 14 15 mov ah, 4ch 16 int 21h 17 18 printStr: 19 push bx 20 push cx 21 push si 22 push di 23 24 mov bx, 0b800H 25 mov es, bx 26 mov di, 0 27 s: 28 mov cl, [si] 29 mov ch, 0 30 jcxz over 31 mov ch, al 32 mov es:[di], cx 33 inc si 34 add di, 2 35 jmp s 36 37 over: 38 pop di 39 pop si 40 pop cx 41 pop bx 42 ret 43 44 code ends 45 end start
把line3改为:strdb ‘another try‘, 0
改变了内容
把line12改为:mov al, 4
改变了字体颜色
基于运行结果,理解源代码,以及,组合使用转移指令call和ret实现子程序的原理与方法。
答:保留现场,将子程序运行前寄存器的值保留下来,运行结束后再还原,不干扰原程序的运行,不改变它的值。避免了程序间的冲突和错误。
答:将字符内容和它的颜色属性存入指定的显存中,打印到屏幕上。
3. 实验任务3
使用任意文本编辑器,录入汇编源程序task3.asm。
子程序num2str:功能:把0~2559之间的任意整数转换成数字字符串,
例如,把1984转换成‘1984‘入口参数要转换的整数 —> ax数字字符串的起始地址 —> ds:di (其中:数字字符串所在段的段地址—> ds,字符串起始地址的偏移地址—>di)出口参数:无
1 assume cs:code, ds:data 2 data segment 3 x dw 1984 4 str db 16 dup(0) 5 data ends 6 7 code segment 8 start: 9 mov ax, data 10 mov ds, ax 11 mov ax, x 12 mov di, offset str 13 call num2str 14 15 mov ah, 4ch 16 int 21h 17 18 num2str: 19 push ax 20 push bx 21 push cx 22 push dx 23 24 mov cx, 0 25 mov bl, 10 26 s1: 27 div bl 28 inc cx 29 mov dl, ah 30 push dx 31 mov ah, 0 32 cmp al, 0 33 jne s1 34 s2: 35 pop dx 36 or dl, 30h 37 mov [di], dl 38 inc di 39 loop s2 40 41 pop dx 42 pop cx 43 pop bx 44 pop ax 45 46 ret 47 code ends 48 end start
子任务1对task3.asm进行汇编、链接,得到可执行程序后,在debug中使用u命令反汇编,使用g命令执行到line15(程序退出之前),使用d命令查看数据段内容,观察是否把转换后的数字字符串‘1984‘存放在数据段中str标号后面的单元。
可以看到存入单元内。
子任务2
对task3.asm源代码进行修改、完善,把task2.asm中用于输出以0结尾的字符串的子程序加进来, 实现对转换后的字符串进行输出。
把task3.asm源代码中,line3中整数改成0~2559之间的任意数值,运行测试,观察结果。
4. 实验任务4
使用任意文本编辑器,录入汇编源程序task4.asm。
1 assume cs:code, ds:data 2 data segment 3 str db 80 dup(?) 4 data ends 5 6 code segment 7 start: 8 mov ax, data 9 mov ds, ax 10 mov si, 0 11 12 s1: 13 mov ah, 1 14 int 21h 15 mov [si], al 16 cmp al, ‘#‘ 17 je next 18 inc si 19 jmp s1 20 next: 21 mov cx, si 22 mov si, 0 23 s2: mov ah, 2 24 mov dl, [si] 25 int 21h 26 inc si 27 loop s2 28 29 mov ah, 4ch 30 int 21h 31 code ends 32 end start
运行结果:
汇编、链接、运行程序,输入一个字符串并以#结束(比如,2020, bye#)观察运行结果。结合运行结果,理解程序功能,了解软中断指令。
具体地:line12-19实现的功能是?
答:利用软中断指令,int 21h中的1号子功能,将输入的字符串中“#”前的字符存储到指定的栈断中。
line21-27实现的功能是?
答:统计“#”前的字符个数作为循环次数,利用2号子功能在屏幕上输出。
5. 实验任务5
在visual studio集成环境中,编写一个简单的包含有函数调用的c程序。代码如下:
#include <stdio.h> int sum(int, int); int main() { int a = 2, b = 7, c; c = sum(a, b); return 0; } int sum(int x, int y) { return (x + y); }
在line7, line13分别设置断点,在调试模式下,查看反汇编代码。
line7断点:
进入sum子函数中,line13断点:
分析反汇编代码,从汇编的角度,观察高级语言中参数传递和返回值是通过什么实现的,以及,参数入栈顺序,返回值的带回方式,等等。
答:高级语言中参数传递和返回值都是通过寄存器实现的。
参数入栈顺序自右向左,b的值传入寄存器eax,a的值传入寄存器ecx,之后使用call指令调用子函数sum
在函数内将结果存入了eax中。返回主函数中,eax的值传给c。
五、实验总结
1、进一步了解总结了之前实验中的显存区域输出,实际操作了课上讲解的内容,屏幕位置的具体计算。
2、了解和使用了软中断指令。
原文:https://www.cnblogs.com/zzzzero/p/14153927.html