| 
 | 
 
 
发表于 2021-1-1 21:00:23
|
显示全部楼层
 
 
 
 本帖最后由 jackz007 于 2021-1-1 21:14 编辑  
 
       问题出在堆栈不平衡,在用 debug 跟踪时,进入 show_str 时记录 sp 值,在要执行 ret 指令前,再看看 sp 值是否和前面记录的值一样?为什么会不一样,因为你在函数中使用了 push cx ,而在函数退出前,没有相应的退栈操作, 只要把 pop cx 指令提前到 jcxz ok 指令之前就可以解决问题。 
       我给楼主写了一份代码,供楼主参考。 
- data segment public para 'data'
 
 -         db 'welcome to masm!',0
 
 - data ends
 
  
- stack segment stack para 'stack'
 
 -         db 800h dup (0)
 
 - stack ends
 
  
- code segment public para 'code'
 
 -     assume cs:code,ds:data
 
 - start:mov ax,data
 
 -           mov ds,ax
 
 -           mov bx,0
 
 -           mov dh,13                    ;行
 
 -           mov dl,32                    ;列
 
 -           mov cl,0fh                   ;颜色
 
 -           mov si,0                     ;ds:si指向字符串的首地址
 
 -           push dx                      ;行列值入栈
 
 -           push si                      ;待显示字符串偏移入栈
 
 -           push cx                      ;字符颜色值入栈
 
 -           call show_str
 
 -           xor ax,ax
 
 -           int 16h
 
 - stop: mov ax,4c00h
 
 -           int 21h
 
  
- show_str: push bp                      ; 在函数入口先保护现场,避免各寄存器的值因调用本函数而被改变
 
 -           mov bp,sp
 
 -           push ax                      
 
 -           push bx
 
 -           push cx
 
 -           push dx
 
 -           push si
 
 -           push di
 
 -           push ds
 
 -           push es
 
 -           mov ax,0b800h
 
 -           mov es,ax
 
 -           mov si , word ptr[bp+06h]    ; 待显示字符串偏移值
 
 -           mov bx , word ptr[bp+08h]    ; 行列值
 
 -           mov al,bh
 
 -           dec al
 
 -           mov cl,0a0h
 
 -           mul cl
 
 -           mov di,ax
 
 -           dec bl
 
 -           xor bh,bh
 
 -           shl bx,1
 
 -           add di,bx                    ; di = 行列值对应的显存偏移
 
 -           mov bx, word ptr[bp+04]      ; 颜色
 
 -           cld
 
 - s1:       lodsb                        ; 从 ds:si 读入1个字符到 al
 
 -           or al,al                     ; 是结束标志字符吗
 
 -           jz s2                        ; 如果是结束字符就跳走
 
 -           stosb                        ; 把 al 存入显存 es:di
 
 -           mov al,bl                    ; 把颜色字节交给al
 
 -           stosb                        ; 把颜色字节存入显存 es:di  
 
 -           jmp short s1                 ; 跳回显示下一个字符
 
 - s2:       pop es                       ; 开始恢复现场
 
 -           pop ds
 
 -           pop di
 
 -           pop si
 
 -           pop dx
 
 -           pop cx
 
 -           pop bx
 
 -           pop ax
 
 -           mov sp,bp
 
 -           pop bp
 
 -           ret
 
 - code ends
 
 - end start
 
  复制代码 |   
 
 
 
 |