王爽《汇编语言》实验10:编写子程序show_str 解答


我自己也想过一个子程序,但运行出来的结果是一些带颜色的表情包,实在是困惑,上网搜查到下面的结果:

这里面有几个地方是我之前没考虑到的:

1、设置显存范围时,我没考虑显示缓冲区与之前的内存设置上的不同,

    偏移000~09f对应显示器上的第一行(80个字符占160个字节)

    偏移0a0~13f对应显示器上的第二行

    偏移140~1df对应显示器上的第三行

所以:第8行为8*160,注意行号减一,因为行号是从0开始;

    同时在一行中:

    00~01单元对应显示器上的第一列

    02~03单元对应显示器上的第二列

    04~05单元对应显示器上的第三列

所以:第三列为2*3,注意减二,因为行号是从0开始。

传值时,将上面直接用一个通用寄存器bx表示。

2、这道题有一个小技巧,即cx的使用,因为一个字符占两个字节的存储空间,低位字节存储ascii码,高位字节存储字符的属性。jcxz判断的是cx是否为0,所以可以先设置al存cl(题意中的颜色属性),将字符值送至cl,再传给低位字节。这样可以避免子程序内容用到栈(我用栈一直出错)。

  1. assume cs:code,ds:data  
  2.   
  3. data segment  
  4.     db 'Welcome to masm!',0  
  5. data ends  
  6.   
  7. code segment  
  8. start:    
  9.     mov dh,8    ;行号  
  10.     mov dl,3    ;列号  
  11.     mov cl,07h  ;白色字      
  12.     mov ax,data  
  13.     mov ds,ax  
  14.     mov si,0    ;循环加入字  
  15.     call show_str  
  16.   
  17.     mov ax,4c00h  
  18.     int 21h  
  19. show_str:  
  20.     push cx ;保存用到的寄存器  
  21.     push si  
  22.     push es  
  23.     push di  
  24.     push bx  
  25.   
  26.     mov ax,0b800h  
  27.     mov es,ax  
  28.   
  29.     mov al,0a0h ;一行的总列数160字节  
  30.     dec dh      ;行号减1,因为是从0开始的  
  31.     mul dh      ;计算行开始偏移地址  
  32.     mov bx,ax  
  33.   
  34.     mov al,2  
  35.     mul dl      ;计算列  
  36.     sub ax,2    ;列也是从0开始,而且一个字符占两个字节  
  37.     add bx,ax   ;求出开始位置   
  38.       
  39.     mov di,0  
  40.     mov al,cl  
  41.     mov ch,0    ;高8位为0  
  42. s:    
  43.     mov cl,ds:[si]  ;判断是否到了字符结束  
  44.     jcxz ok  
  45.     mov es:[bx+di],cl  
  46.     mov es:[bx+di+1],al  
  47.   
  48.     inc si  
  49.     add di,2  
  50.     jmp short s  
  51. ok:  
  52.     pop bx  
  53.     pop di  
  54.     pop es  
  55.     pop si  
  56.     pop cx  
  57.     ret  
  58.   
  59. code ends  
  60.   
  61. end start  


猜你喜欢

转载自blog.csdn.net/qq_36998053/article/details/80782674