assume cs:code,ds:data,ss:stackdata segment db 'welcome to masm!' ;定义要显示的字符串(共16字节) db 02h,24h,71h ;分别定义三行的属性,即定义三种颜色属性data endsstack segment dw 8 dup (0) ;定义一个栈段,用于暂存数据,存储ax、bx等寄存器值 ;因为这些寄存器是16位的,所以定义的栈也是字型的stack endscode segmentstart: mov ax,data mov ds,ax ;将data和ds挂钩 mov ax,stack mov ss,ax ;将stack和ss挂钩 mov sp,10h ;因为栈大小dw 8就是16个字节,所以栈的初始地址 ;指向栈顶,也是16个字节,即十六进制表示为10h xor bx,bx ;bx清零,用来索引颜色。相当于mov bx,0 ;即bx用来索引颜色 mov ax,0b872h ;屏幕总共显示25行,中间3行是12、13、14 ;算出屏幕第12行中间的显存的段起始位置放入ax中 ;前面有11行,每行160个字节:11*160=1760 ;即第12行的开始地址为1760,现要求显示在中间 ;打印16个字符的字符串。每行有80个字符,也就是 ;前面32个字符,后面32个字符,中间正好16个字符。 ;32个字符,每个字符占2个字节(第一个字节表示字 ;符,第二个字节表示属性),32*2=64。 ;1760+64=1824(十六进制:720h) ;因为显存的起始地址为 b8000h,b8000h+720h=b8720h ;我们把它当成一个段地址就是b872h,该地址其实就是字符 ;串起始字符w的地址。 mov cx,3 ;s3循环控制行数,外循环为3次,因为要显示3行字符串s3: push cx ;三个进栈操作为外循环s3保存相关寄存器的值 push ax ;以防止它们的值在内循环中被破坏,因为内层 push bx ;循环用到了相关寄存器,值会被覆盖 mov es,ax ;此时es为屏幕第12行中间的显存的段起始位置 mov si,0 ;si用来索引字符串的每个字符 mov di,0 ;di用来确定每个字符的偏移地址 mov cx,10h ;s1循环实现每行16个字符的写入,内循环为16次,因为字符串中含16个字节s1: mov al,ds:[si] ;比如ds:[0]就是数据段的w字符 mov es:[di],al ;相应es:[di]=b872:0处显示w的效果 inc si add di,2 ;di是要加2的,因为2个字节确定一个字符的显示效果 loop s1 ;循环16次,实现偶地址中存放字符 mov di,1 ;di的值设为1,从而为在显存奇地址中存放字符的颜色属性作准备 pop bx mov al,ds:10h[bx] ;取颜色属性存放在al中。ds:10h[bx]指向数据段中的02h inc bx ;bx加1,为取下一行颜色属性作准备 mov cx,10h ;第二个内循环也为16次s2: mov cs:[di],al add di,2 ;di初值1,每次循环加2。正好实现在每个字符的第二个字节单元填充颜色属性 loop s2 ;此循环实现奇地址中存放字符的颜色属性 ;以下4句为下一趟外循环作准备 pop ax add ax,0ah ;将显存的段起始地址设为当前行的下一行 ;[在段地址中加0ah,相当于在偏移地址中加了0a0h(=160d)] pop cx loop s3 mov ax,4c00h int 21hcode endsend start
附: