. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->转移指令的原理
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  【分享我的实验9】已调试通过,一个循环,带超详细注释、地址算法,带高亮闪烁效果(书上未要求高亮闪烁效果)  [待解决] 回复[ 4次 ]   点击[ 339次 ]  
assembly31
[帖 主]   [ 发表时间:2011-02-07 19:37 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2011-02-07 19:07
d segment

db 'welcome to masm!'

;'welcome to masm!'共有16个字符(不算引号),welcome七个,空格一个,to两个,空格一个,masm!五个

d ends

assume cs:c,ds:d

c segment

k:
mov ax,d
mov ds,ax

;将ds指向d段

mov ax,0b800h
mov es,ax

;将es指向b800h

mov bx,0
mov si,0
mov di,0

;相关寄存器初始化

mov cx,16

;设置循环次数(从标记X处开始到loop x之间的程序将重复执行16次)

x:
mov bx,1824

;将es:[bx][si]指向显存中第一行第一个要写入的数据的地址
;(以后每次循环后将换回第一行并指向后一个的地址)

;1824是怎么算出来的呢
;书上要求在屏幕中间显示字符串,对于80*25模式,显示器可以显示25行(横的)80列(竖的)的共25*80个字符
;因为要显示3行'welcome to masm!'(引号不算,共16个字符)
;那么在分别从第12,13,14行的第33列开始显示,则正好为屏幕中间
;(上空1到11行,下空15到25行,上下都空11行;左空1到32列,从33到48列显示字符,右空49到80列,左右都空32列)
;上空的11行空去了11*80=880个字符,第12行左边还要再空去32列(32个字符),则一共空去了880+32=912个字符
;每个字符占2个字节(ASCII码一个,属性一个),则一共空去了912*2=1824个字节
;因为字符在显存中不分行列(行和列只是对于显示器显示字符的形式)从B800H:0000开始的地址连续存储
;要空去1824个字节也就是要将从B800H:0000到B800H:1823的地址跳过,从B800H:1824的地址开始写入

mov al,[di]

;将ds:[di]所指的字符串(welcome to masm!)中的字符的ASCII码值存进al
;(当前指向第一个字母w的ASCII码值,循环后指针将逐次按单位字节后移)

mov ah,8ah

;将高亮闪烁绿字的属性字节存进ah

mov es:[bx][si],ax

;将高亮闪烁绿字w的ASCII码值和属性字节同时写入显存中的指定位置(循环后将依次写入后面的字符)

add bx,160

;换到下一行

mov ah,0ach

;将绿底高亮闪烁红字的属性字节存进ah

mov es:[bx][si],ax

;将绿底高亮闪烁红字w的ASCII码值和属性字节同时写入显存中的指定位置(同上)

add bx,160

;换到下一行

mov ah,0f9h

;将白底高亮闪烁蓝字的属性字节存进ah

mov es:[bx][si],ax

;将白底高亮闪烁蓝字w的ASCII码值和属性字节同时写入显存中的指定位置(同上)

add si,2

;si后移2字节位置,实现在每次循环后将es:[bx][si]指向显存中每一行后一个要写入的字符的地址

inc di

;di后移1字节位置,实现在每次循环后将ds:[di]指向字符串中后一个字符的ASCII码值

loop x

;跳转到标记x处重复执行
;loop x这条指令将执行16次,每执行一次cx减1,执行第16次的时候cx为0,循环结束
;实现从标记x处开始到loop x之间的程序重复执行16次

mov ax,4c00h
int 21h

;程序返回,貌似是返回到debug(将cpu的控制权交还给使这个实验得以运行的程序debug)
;至于喂神马这两条指令就能实现程序返回,偶也不懂

c ends

end k

;指明程序的入口从标记k处开始(程序加载后将cs:ip指向标记k处的第一条指令的地址)
zaixuexi
[第1楼]   [ 回复时间:2011-02-07 20:06 ]   [引用]   [回复]   [ top ] 
荣誉值:93
信誉值:0
注册日期:2010-11-29 14:28
很不错,呵呵
masmaster
[第2楼]   [ 回复时间:2011-02-07 23:41 ]   [引用]   [回复]   [ top ] 
荣誉值:268
信誉值:12
注册日期:2010-06-18 22:19
不错~~~
youguiqing
[第3楼]   [ 回复时间:2011-03-08 00:51 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:0
注册日期:2009-12-03 21:13
assume cs:code,ds:data,ss:stack 
data segment
db 'Welcome to masm!'
dw 02h,24h,71h       ;三种颜色的代码
data ends
stack segment
dw 8 dup(0)
stack ends
code segment
           start:mov ax,data    ;设置字符所在为ds段
                  mov ds,ax
                  mov ax,stack    ;设置载空间
                  mov ss,ax
                  mov sp,16
                  mov ax,0b800h   ;设置输出为ES段
                  mov es,ax
                  mov bp,1030 ;bp=80*12行+70=1030差不多在中间了
                  mov si,16   ;设置si为颜色所在内存地址
                  mov cx,3    ;显示3行所以设外层loop为3
            s1:mov di,0
               mov bx,0
               push cx        ;外层loop用来保存cx值          
                  mov cx,16
                s:push [bx]  ;把ds:0中的字显示到屏幕第12行中间
                  pop es:[bp+di] ;这里用di来每显一个字后向2字节
                  push [si]     ;把颜色输入
                  pop es:1[bp+di]
                  inc bx
                  add di,2   ;这里用di来每显一个字后向2字节
                  loop s
                  add si,2   ;换一种颜色
                  add bp,160 ;屏幕显示换一行
                  pop cx    ;取回外层loop的CX值
                  loop s1
                  mov ax,4c00h
                  int 21h
code ends
end start
450822769
[第4楼]   [ 回复时间:2011-03-08 23:22 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2010-12-18 12:40
在内循环写完一行后,进行外循环时为什么bx不重新清零啊?我试着把bx清零,程序依然正确运行...这是为什么呢?
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved