|
发表于 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
复制代码 |
|