. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->转移指令的原理
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  实验九,大家看看,经过测试能显示。  [已解决] 回复[ 5次 ]   点击[ 511次 ]  
towersimper
[帖 主]   [ 发表时间:2010-07-23 14:31 ]   [引用]   [回复]   [ top ] 
荣誉值:9
信誉值:3
注册日期:2008-06-12 09:16
assume ds:data,ss:stack,cs:code 
 ;由于字符串数据长16字节,每个字符其对应的ascii码和字符属性在显示缓冲区中各占一个字节,故共占32个字节,远小于一页总共能显示的4000个字节,故在此只需选择第0页来显示所需显示的字符串。在第0页中,共25行,每行80个字符,由于每个字符对应的在显示缓冲区各占一个字节,故每行共160个字节。要显示的字符串在显示缓冲区分别以3种不同的颜色属性显示,那就需3行来显示,即分别位于第11,12,13行,且题目中要求显示的字符串位于屏幕中央,即位于上述三行中每行的64~95字节处。在本程序中,上述三行的段地址用es表示,由题可知 
(es)=0B800h,第十一行开始处的偏移地址为第0行开始处的偏移地址加上中间11行的长度,即0000h+11*160=06E0h,用bx表示。另外字符串位于每行的64~95字节处,则第64字节离每行起始处的距离为40h,由于每个字符串从第64字节处占2个字节,因此用变量di每次循环加2,共循环16次,遍历这段存储空间。另外这三行中每行字符串对应位置相差160个字节,因此把(bx)+160就会切换到下一行。可知外循环为3次循环,在每行之间切换,内循环为16次循环,在每行中,将要显示的字符串中的每个字符的ascii码和对应的颜色属性分别传送到显示缓冲区中的第11,12,13行中的64~95字节处。 
data segment 
db 'welcome to masm!'     ;显示在屏幕中央的由16个字符组成的,总共长16个字节的字符串数据 
db 02h,24h,71h            ;分别代表绿色,绿底红色,白底蓝色 
data ends 

stack segment 
db 16 dup (0)              ;用来构建长16个字节的栈 
stack ends  

code segment               
start: mov ax,0B800h    
mov es,ax                  ;以上两指令将显示缓冲区的段地址传送给es 
mov ax,data                  
mov ds,ax                  ;以上两指令将数据段段地址传送给ds 
mov ax,stack 
mov ss,ax                    
mov sp,10h                 ;以上三条指令将栈段段地址传送给ss,栈顶指针指向10h,即起始时栈空 
mov si,0                   ;外循环的变量段地址si初始值为0 
mov di,0                   ;外循环di,每次循环增加1 
mov bx,06E0h               ;要显示的显示缓冲区的行偏移地址 
mov cx,3                   ;外循环循环次数 
s0:  push cx               ;由于内循环也要用cx,现将外循环的cx入栈保护起来,以便出栈后恢复 
push si                    ;由于内循环也用到si,将si保护起来,出栈后保持每行的内循环的si初始值为0 
push di                    ;由于内循环也要用到di,其内循环di每次增加2,将外循环的di保护起来,使其不受内循环的di影响 
mov ah,ds:[di+10h]         ;将数据段的颜色传给ah 
mov cx,16                  ;内循环的循环次数为16 
mov di,0                   ;保证每行内循环的di初始值为0 
s: mov al,ds:[si] 
mov es:[bx+di+40h],al 
mov es:[bx+di+41h],ah    
inc si                            
add di,2 
loop s                     ;内循环中的所有指令是将每个字符的ascii码(存储在al中)和颜色属性(存储在ah中)传送到每行的64~95字节中。 
pop di                     ;恢复外循环的di值 
pop si                     ;恢复外循环的si值 
pop cx                     ;恢复外循环的cx值 
add bx,0A0h                ;转移到一行 
inc di                     ;外循环di每次加1,从而选择数据段中三种不同的属性,分别传送给相应的三行中 
loop s0 
code ends 
end start
towersimper
[第1楼]   [ 回复时间:2010-07-23 14:32 ]   [引用]   [回复]   [ top ] 
荣誉值:9
信誉值:3
注册日期:2008-06-12 09:16
在dos下先编译连接后,然后运行可执行文件。显示效果的时候,通过cmd进入dos后,通过按下Alt+Enter键,全屏观看,不然不时会出现问题。程序中不少地方注释太长,只是为了方便理解,实际测试应将这些注释去掉,不然会提示好几处注释内容太长的警告信息。
towersimper
[第2楼]   [ 回复时间:2010-07-23 15:14 ]   [引用]   [回复]   [ top ] 
荣誉值:9
信誉值:3
注册日期:2008-06-12 09:16
assume ds:data,ss:stack,cs:code 
 ;由于字符串数据长16字节,每个字符其对应的ascii码和字符属性在显示缓冲区中各占一个字节,故共占32个字节,远小于一页总共能显示的4000个字节,故在此只需选择第0页来显示所需显示的字符串。在第0页中,共25行,每行80个字符,由于每个字符对应的在显示缓冲区各占一个字节,故每行共160个字节。要显示的字符串在显示缓冲区分别以3种不同的颜色属性显示,那就需3行来显示,即分别位于第11,12,13行,且题目中要求显示的字符串位于屏幕中央,即位于上述三行中每行的64~95字节处。在本程序中,上述三行的段地址用es表示,由题可知 
(es)=0B800h,第十一行开始处的偏移地址为第0行开始处的偏移地址加上中间11行的长度,即0000h+11*160=06E0h,用bx表示。另外字符串位于每行的64~95字节处,则第64字节离每行起始处的距离为40h,由于每个字符串从第64字节处占2个字节,因此用变量di每次循环加2,共循环16次,遍历这段存储空间。另外这三行中每行字符串对应位置相差160个字节,因此把(bx)+160就会切换到下一行。可知外循环为3次循环,在每行之间切换,内循环为16次循环,在每行中,将要显示的字符串中的每个字符的ascii码和对应的颜色属性分别传送到显示缓冲区中的第11,12,13行中的64~95字节处。 
data segment 
db 'welcome to masm!'     ;显示在屏幕中央的由16个字符组成的,总共长16个字节的字符串数据 
db 02h,24h,71h            ;分别代表绿色,绿底红色,白底蓝色 
data ends 

stack segment 
db 16 dup (0)              ;用来构建长16个字节的栈 
stack ends  

code segment               
start: mov ax,0B800h    
mov es,ax                  ;以上两指令将显示缓冲区的段地址传送给es 
mov ax,data                  
mov ds,ax                  ;以上两指令将数据段段地址传送给ds 
mov ax,stack 
mov ss,ax                    
mov sp,10h                 ;以上三条指令将栈段段地址传送给ss,栈顶指针指向10h,即起始时栈空 
mov si,0                   ;外循环的变量段地址si初始值为0 
mov di,0                   ;外循环di,每次循环增加1 
mov bx,06E0h               ;要显示的显示缓冲区的行偏移地址 
mov cx,3                   ;外循环循环次数 
s0:  push cx               ;由于内循环也要用cx,现将外循环的cx入栈保护起来,以便出栈后恢复 
push si                    ;由于内循环也用到si,将si保护起来,出栈后保持每行的内循环的si初始值为0 
push di                    ;由于内循环也要用到di,其内循环di每次增加2,将外循环的di保护起来,使其不受内循环的di影响 
mov ah,ds:[di+10h]         ;将数据段的颜色传给ah 
mov cx,16                  ;内循环的循环次数为16 
mov di,0                   ;保证每行内循环的di初始值为0 
s: mov al,ds:[si] 
mov es:[bx+di+40h],al 
mov es:[bx+di+41h],ah    
inc si                            
add di,2 
loop s                     ;内循环中的所有指令是将每个字符的ascii码(存储在al中)和颜色属性(存储在ah中)传送到每行的64~95字节中。 
pop di                     ;恢复外循环的di值 
pop si                     ;恢复外循环的si值 
pop cx                     ;恢复外循环的cx值 
add bx,0A0h                ;转移到一行 
inc di                     ;外循环di每次加1,从而选择数据段中三种不同的属性,分别传送给相应的三行中 
loop s0 
code ends 
end start
------------------
回复:对了在loop so与code ends之间应该添加mov ax,4c00h和int 21h两条指令。
towersimper
[第3楼]   [ 回复时间:2010-07-23 15:18 ]   [引用]   [回复]   [ top ] 
荣誉值:9
信誉值:3
注册日期:2008-06-12 09:16
在dos下先编译连接后,然后运行可执行文件。显示效果的时候,通过cmd进入dos后,通过按下Alt+Enter键,全屏观看,不然不时会出现问题。程序中不少地方注释太长,只是为了方便理解,实际测试应将这些注释去掉,不然会提示好几处注释内容太长的警告信息。
------------------
回复:其中不许全屏也可观看这个效果,主要还是没有mov ax,4c00h 和int 21h 这两条指令。汗啊。
towersimper
[第4楼]   [ 回复时间:2010-07-23 15:19 ]   [引用]   [回复]   [ top ] 
荣誉值:9
信誉值:3
注册日期:2008-06-12 09:16
在dos下先编译连接后,然后运行可执行文件。显示效果的时候,通过cmd进入dos后,通过按下Alt+Enter键,全屏观看,不然不时会出现问题。程序中不少地方注释太长,只是为了方便理解,实际测试应将这些注释去掉,不然会提示好几处注释内容太长的警告信息。
------------------
回复:其中不须全屏也可观看这个效果,主要还是没有mov ax,4c00h 和int 21h 这两条指令。汗啊。
------------------
回复:加了这两条指令后,就没有上述问题了。
towersimper
[第5楼]   [ 回复时间:2010-07-23 15:19 ]   [引用]   [回复]   [ top ] 
荣誉值:9
信誉值:3
注册日期:2008-06-12 09:16
此贴由 贴主 于 [ 2010-07-23 15:19 ] 结贴。 结贴原因:问题已解决
得分情况:
此问题已结贴!
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved