- [cutebe] 相当牛,这个苦思冥想也值了。^_^ 11/30 00:00
- [parse] 如果忽略消息循环,那么操作系统加载的程序很快就执行完了,就像DOS程序一闪而过,所以CPU会空闲下来 06/30 09:04
- [游客] 楼主好厉害,挺一下! 01/19 08:43
- [游客] 很不错。 01/04 18:36
- [chinatree] 潜力贴留名,沙发。 11/08 12:58
- [youthangel] 恩,这次对了 10/30 18:56
- [fpamc] mov bx,18 在这条指令的上边是不是要加一条sub dx,dx? 10/30 10:03
- [fpamc] 对的 10/27 11:19
- [fpamc] 对的 10/27 09:00
- [fpamc] 哦,对不起,看错了。实验13也有一个7ch中断 10/27 08:52
- [游客] 现在急需一个汇编大作业。。。。。。可以么。。。。。如果今天之内看见留言 就加 1765496715 12/28 16:52
- [youthangel] 这算是对我学习的鼓励吗?谢谢!咱们这样交流就可以了 10/11 15:48
- [fpamc] 多日观察,你的学习积极性挺高的。可以来我们群了。群号:75916434 10/11 10:58
[2012-10-12 15:12] 实验十
这个实验主要练习子程序的书写,重点把握现场保护与恢复、参数的传递和返回,相当于C中的函数
掌握了这些我们以后就可以写一些大程序了,比如贪吃蛇、俄罗斯方块啊等等
1、显示字符串
comment ;
实验十 第一题
编写显示子程序,在指定位置显示指定格式的字符串
;
assume cs:code,ds:data
data segment
db 'welcome to masm!',0
data ends
code segment
start:
mov dh,8 ;行
mov dl,3 ;列
mov ax,data
mov ds,ax ;数据来源
mov si,0 ;偏移量
call show_str
;暂停
mov ah,1
int 21h
;退出
mov ax,4c00h
int 21h
comment ;-----------显示子程序----------------
功能:在指定位置显示一串以0结束的字符
参数:dh行,dl列,字符显示属性 数据段的10h处
返回:无
;
show_str:
push di
push es
push ax ;保护现场
mov al,160
mul dh ;算出第8行在显存中的位置
mov di,ax
add dl,dl
;算出第3列在第八行的第几个内存单元
add di,ax ;算出显存的开始单元
mov ax,0b800h
mov es,ax ;初始es
;开始显示
s:
mov al,[si]
cmp al,0
je return
mov es:[di],al
mov al,2
mov es:[di+1],al
inc si
add di,2
jmp s
;显示结束
return:
pop ax ;回复现场
pop es
pop di
ret
code ends
end start
2、解决除法溢出的问题
comment ;
解决除法溢出的问题
1、计算出
mov bh,1
mov ax,1000
div bh
的结果
2、计算出
mov ax,1000h
mov dx,1
mov bx,1
div bx
的结果
;
assume cs:code
code segment
start:
mov ax,1000h ;被除数低八位
mov dx,1 ;被除数高八位
mov bx,1 ;除数
call divdw ;32位的除法溢出
mov bh,1
mov ax,1000
call divw ;16位的除法溢出
;退出
mov ax,4c00h
int 21h
;------------------子程序 16位的除法溢出--------------------------
comment ;
功能:解决16位除法溢出问题
参数:ax被除数,bh除数
返回:ax 商,bh余数
;
divw: ;15位的除法溢出
;保护现场
push dx
;开始运算
mov dl,al ;保存低位
mov al,ah
mov ah,0
div bh ;商在al中,余数在ah中
mov dh,al ;保存高位商
mov al,dl ;在次组成16位
div bh
mov bh,ah ;余数放在bh中
mov ah,dh ;商放在ax中
;运算结束,结果:商在ax中,余数在bh中
pop dx
;恢复现场
ret
;------------------子程序32位的除法溢出--------------------------
comment ;
功能:解决32位除法溢出问题
参数:dx ax被除数,bx除数
返回:dx ax 商,cx余数
;
divdw: ;32位的除法溢出
;保护现场
;开始运算
push ax ;把低位保存起来
mov ax,dx
mov dx,0
div bx ;高八位的商在ax中,余数在dx中
mov cx,ax ;把高位商给cx
pop ax ;低位出栈
div bx ;低位商在ax中,余数在dx中
xchg cx,dx ;dx和cx中的数据交换
;运算结束,结果:商在dx:ax中,余数在cx中
;恢复现场
ret
code ends
end start
3、数值显示
comment ;
将data段中的数据以十进制的形式显示在屏幕上
算法分析:
1、数据在内存中是以十六进制的形式存储,先用连除取余将十六进制转换成十进制,暂存到栈里
2、防止除法溢出需用到上一题的算法
3、指定位置显示用到第一题的算法
4、得到十进制数还要转换成去对应ASCII形式
不足之处:
1、没必要每次都安除法溢出处理
2、结构化思想不够熟练
失误:
1、开始时,没有进行单元测试,写了一大坨代码,结果不能运行
2、模块之间的衔接(传参和返回)没能灵活把握,以致子程序返回出错
3、意志不坚定,当代码乱成一坨的时候,没耐心改完,以致耽误了一晚上的时间
;
assume cs:code,ds:data,ss:stack
data segment
dw 123,12666,1,8,3,38 ;要显示的原始数据
data ends
temp segment
dw 8 dup(0) ;数据暂存空间
temp ends
stack segment
dw 8 dup(0)
stack ends
code segment
start:
;es:di指向显存
;ds:si指向数据段
;ss:sp 指向栈段
mov ax,stack
mov ss,ax
mov sp,10h ;初始化栈
mov si,0
mov dh,8 ;行
mov dl,3 ;列
mov cx,6
s:
;第一步 一个数转换成十进制数,每一位入栈,正好倒过来
mov ax,data
mov ds,ax
mov ax,[si] ;被除数
mov bp,0 ;初始化计数器bp,记录前的16进制数产生了多少个10进制数
s0:
mov bx,10 ;除数,同时把bh置零
call divw ;16位的除法溢出
cmp bl,0 ;判断是否除完
je c
push bx ;每一个十进制数入栈
inc bp ;记录个数
jmp s0
;第二步从栈中取出一个数的每一位转换成对应ASCII ,放入指定位置
c:
mov ax,temp
mov ds,ax
mov bx,0 ;规定指定位置ds:[bx]
s2:
pop ax ;从栈中取数据
dec bp ;计数器减一
mov [bx],al ;放到指定位置
inc bx ;指向下一个指定位置
cmp bp,0 ;判断是否取完了
jne s2
mov al,0 ;结尾处放一个0,相当于C语言中字符串的结尾'\0'
mov [bx],al ;结尾是 0
;第三步指定位置显示
mov ax,temp
mov ds,ax ;传参
push si ;si入栈,方便指向临时存储段中数据
mov si,0 ;指向第一个字符
call show_str ;显示字符
pop si ;si出栈
add dl,8 ;列加8,相当于一个制表符
add si,2 ;si加二指向下一个字
dec cx ;循环控制变量减一
cmp cx,0 ;检测循环次数
jne far ptr s ;进入下一次循环
;暂停
mov ah,1
int 21h
;退出
mov ax,4c00h
int 21h
;------------------子程序 16位的除法溢出--------------------------
comment ;
功能:解决16位除法溢出问题
参数:ax被除数,bl除数
返回:ax 商,bh余数
;
divw: ;15位的除法溢出
;保护现场
push dx
;开始运算
mov dl,al ;保存低位
mov al,ah
mov ah,0
div bl ;商在al中,余数在ah中
mov dh,al ;保存高位商
mov al,dl ;在次组成16位
div bl
mov bl,ah ;余数放在bh中
mov ah,dh ;商放在ax中
;运算结束,结果:商在ax中,余数在bl中
pop dx
;恢复现场
ret
comment ;-----------显示子程序----------------
功能:在指定位置显示一串以0结束的字符
参数:dh行,dl列 ,数据位置ds:si
返回:无
;
show_str:
push di
push es
push ax ;保护现场
mov al,160
mul dh ;算出第8行在显存中的位置
mov di,ax
add dl,dl
;算出第3列在第八行的第几个内存单元
add di,ax ;算出显存的开始单元
mov ax,0b800h
mov es,ax
;开始显示
s3:
mov al,[si]
cmp al,0
je return
add al,30h
mov es:[di],al ;显示字符
mov al,2
mov es:[di+1],al
inc si
add di,2
jmp s3
;显示结束
return:
pop ax ;回复现场
pop es
pop di
ret
code ends
end start
掌握了这些我们以后就可以写一些大程序了,比如贪吃蛇、俄罗斯方块啊等等
1、显示字符串
comment ;
实验十 第一题
编写显示子程序,在指定位置显示指定格式的字符串
;
assume cs:code,ds:data
data segment
db 'welcome to masm!',0
data ends
code segment
start:
mov dh,8 ;行
mov dl,3 ;列
mov ax,data
mov ds,ax ;数据来源
mov si,0 ;偏移量
call show_str
;暂停
mov ah,1
int 21h
;退出
mov ax,4c00h
int 21h
comment ;-----------显示子程序----------------
功能:在指定位置显示一串以0结束的字符
参数:dh行,dl列,字符显示属性 数据段的10h处
返回:无
;
show_str:
push di
push es
push ax ;保护现场
mov al,160
mul dh ;算出第8行在显存中的位置
mov di,ax
add dl,dl
;算出第3列在第八行的第几个内存单元
add di,ax ;算出显存的开始单元
mov ax,0b800h
mov es,ax ;初始es
;开始显示
s:
mov al,[si]
cmp al,0
je return
mov es:[di],al
mov al,2
mov es:[di+1],al
inc si
add di,2
jmp s
;显示结束
return:
pop ax ;回复现场
pop es
pop di
ret
code ends
end start
2、解决除法溢出的问题
comment ;
解决除法溢出的问题
1、计算出
mov bh,1
mov ax,1000
div bh
的结果
2、计算出
mov ax,1000h
mov dx,1
mov bx,1
div bx
的结果
;
assume cs:code
code segment
start:
mov ax,1000h ;被除数低八位
mov dx,1 ;被除数高八位
mov bx,1 ;除数
call divdw ;32位的除法溢出
mov bh,1
mov ax,1000
call divw ;16位的除法溢出
;退出
mov ax,4c00h
int 21h
;------------------子程序 16位的除法溢出--------------------------
comment ;
功能:解决16位除法溢出问题
参数:ax被除数,bh除数
返回:ax 商,bh余数
;
divw: ;15位的除法溢出
;保护现场
push dx
;开始运算
mov dl,al ;保存低位
mov al,ah
mov ah,0
div bh ;商在al中,余数在ah中
mov dh,al ;保存高位商
mov al,dl ;在次组成16位
div bh
mov bh,ah ;余数放在bh中
mov ah,dh ;商放在ax中
;运算结束,结果:商在ax中,余数在bh中
pop dx
;恢复现场
ret
;------------------子程序32位的除法溢出--------------------------
comment ;
功能:解决32位除法溢出问题
参数:dx ax被除数,bx除数
返回:dx ax 商,cx余数
;
divdw: ;32位的除法溢出
;保护现场
;开始运算
push ax ;把低位保存起来
mov ax,dx
mov dx,0
div bx ;高八位的商在ax中,余数在dx中
mov cx,ax ;把高位商给cx
pop ax ;低位出栈
div bx ;低位商在ax中,余数在dx中
xchg cx,dx ;dx和cx中的数据交换
;运算结束,结果:商在dx:ax中,余数在cx中
;恢复现场
ret
code ends
end start
3、数值显示
comment ;
将data段中的数据以十进制的形式显示在屏幕上
算法分析:
1、数据在内存中是以十六进制的形式存储,先用连除取余将十六进制转换成十进制,暂存到栈里
2、防止除法溢出需用到上一题的算法
3、指定位置显示用到第一题的算法
4、得到十进制数还要转换成去对应ASCII形式
不足之处:
1、没必要每次都安除法溢出处理
2、结构化思想不够熟练
失误:
1、开始时,没有进行单元测试,写了一大坨代码,结果不能运行
2、模块之间的衔接(传参和返回)没能灵活把握,以致子程序返回出错
3、意志不坚定,当代码乱成一坨的时候,没耐心改完,以致耽误了一晚上的时间
;
assume cs:code,ds:data,ss:stack
data segment
dw 123,12666,1,8,3,38 ;要显示的原始数据
data ends
temp segment
dw 8 dup(0) ;数据暂存空间
temp ends
stack segment
dw 8 dup(0)
stack ends
code segment
start:
;es:di指向显存
;ds:si指向数据段
;ss:sp 指向栈段
mov ax,stack
mov ss,ax
mov sp,10h ;初始化栈
mov si,0
mov dh,8 ;行
mov dl,3 ;列
mov cx,6
s:
;第一步 一个数转换成十进制数,每一位入栈,正好倒过来
mov ax,data
mov ds,ax
mov ax,[si] ;被除数
mov bp,0 ;初始化计数器bp,记录前的16进制数产生了多少个10进制数
s0:
mov bx,10 ;除数,同时把bh置零
call divw ;16位的除法溢出
cmp bl,0 ;判断是否除完
je c
push bx ;每一个十进制数入栈
inc bp ;记录个数
jmp s0
;第二步从栈中取出一个数的每一位转换成对应ASCII ,放入指定位置
c:
mov ax,temp
mov ds,ax
mov bx,0 ;规定指定位置ds:[bx]
s2:
pop ax ;从栈中取数据
dec bp ;计数器减一
mov [bx],al ;放到指定位置
inc bx ;指向下一个指定位置
cmp bp,0 ;判断是否取完了
jne s2
mov al,0 ;结尾处放一个0,相当于C语言中字符串的结尾'\0'
mov [bx],al ;结尾是 0
;第三步指定位置显示
mov ax,temp
mov ds,ax ;传参
push si ;si入栈,方便指向临时存储段中数据
mov si,0 ;指向第一个字符
call show_str ;显示字符
pop si ;si出栈
add dl,8 ;列加8,相当于一个制表符
add si,2 ;si加二指向下一个字
dec cx ;循环控制变量减一
cmp cx,0 ;检测循环次数
jne far ptr s ;进入下一次循环
;暂停
mov ah,1
int 21h
;退出
mov ax,4c00h
int 21h
;------------------子程序 16位的除法溢出--------------------------
comment ;
功能:解决16位除法溢出问题
参数:ax被除数,bl除数
返回:ax 商,bh余数
;
divw: ;15位的除法溢出
;保护现场
push dx
;开始运算
mov dl,al ;保存低位
mov al,ah
mov ah,0
div bl ;商在al中,余数在ah中
mov dh,al ;保存高位商
mov al,dl ;在次组成16位
div bl
mov bl,ah ;余数放在bh中
mov ah,dh ;商放在ax中
;运算结束,结果:商在ax中,余数在bl中
pop dx
;恢复现场
ret
comment ;-----------显示子程序----------------
功能:在指定位置显示一串以0结束的字符
参数:dh行,dl列 ,数据位置ds:si
返回:无
;
show_str:
push di
push es
push ax ;保护现场
mov al,160
mul dh ;算出第8行在显存中的位置
mov di,ax
add dl,dl
;算出第3列在第八行的第几个内存单元
add di,ax ;算出显存的开始单元
mov ax,0b800h
mov es,ax
;开始显示
s3:
mov al,[si]
cmp al,0
je return
add al,30h
mov es:[di],al ;显示字符
mov al,2
mov es:[di+1],al
inc si
add di,2
jmp s3
;显示结束
return:
pop ax ;回复现场
pop es
pop di
ret
code ends
end start
评论次数(1) |
浏览次数(274) |
类型(汇编作业) |
收藏此文 |