鱼C论坛

 找回密码
 立即注册
查看: 4573|回复: 3

[汇编作业] 实验10.1求助

[复制链接]
发表于 2021-1-1 17:16:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
经过n个小时的苦思冥想,本吊终于磕磕绊绊的实现了程序,大佬勿喷。

下面有个地方百思不得其解,为什么最后的ok标号处用ret的话就会出问题呢?在debug里跟着发现出现了莫名其妙的指令然后又继续开始执行之前的一些指令,我目前是用的jmp让他强行跳回到stop标号处。

太难了 = =

assume cs:code

data segment
        db 'welcome to masm!',0
data ends

stack segment
        db 8 dup (0)
stack ends

code segment
start:mov ax,data
          mov ds,ax
          mov bx,0
          mov dh,8                ;行
          mov dl,1                ;列
          mov cl,2                ;颜色
          mov si,0                ;ds:si指向字符串的首地址
          call show_str
stop: mov ax,4c00h
          int 21h
          
          
show_str:
                 mov ax,0b800h;
                 mov es,ax
                 sub dh,1
                 mov ah,0
                 mov al,160
                 mul dh
                 mov di,ax        ;行偏移地址存在si中
                 sub dl,1
                 mov ah,0
                 mov al,2
                 mul dl
                 mov bx,ax        ;列偏移地址存在bx中
not_ok:  push cx
                 mov cl,[si];将字符按索引取出放入cl
                 mov ch,0
                 jcxz ok;判断是否为0
                 mov es:[bx+di],cl;将字符放入对应显存位置
                 pop cx;恢复cx的值
                 mov es:[bx+di+1],cl;写入颜色属性
                 add bx,2;移动到下个字节
                 inc si
                 jmp short not_ok
ok:      jmp stop                                        ;就是这里出的问题
                 
          
code ends
end start
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-1-1 21:00:23 | 显示全部楼层
本帖最后由 jackz007 于 2021-1-1 21:14 编辑

       问题出在堆栈不平衡,在用 debug 跟踪时,进入 show_str 时记录 sp 值,在要执行 ret 指令前,再看看 sp 值是否和前面记录的值一样?为什么会不一样,因为你在函数中使用了 push cx ,而在函数退出前,没有相应的退栈操作, 只要把 pop cx 指令提前到 jcxz ok 指令之前就可以解决问题。
       我给楼主写了一份代码,供楼主参考。
  1. data segment public para 'data'
  2.         db 'welcome to masm!',0
  3. data ends

  4. stack segment stack para 'stack'
  5.         db 800h dup (0)
  6. stack ends

  7. code segment public para 'code'
  8.     assume cs:code,ds:data
  9. start:mov ax,data
  10.           mov ds,ax
  11.           mov bx,0
  12.           mov dh,13                    ;行
  13.           mov dl,32                    ;列
  14.           mov cl,0fh                   ;颜色
  15.           mov si,0                     ;ds:si指向字符串的首地址
  16.           push dx                      ;行列值入栈
  17.           push si                      ;待显示字符串偏移入栈
  18.           push cx                      ;字符颜色值入栈
  19.           call show_str
  20.           xor ax,ax
  21.           int 16h
  22. stop: mov ax,4c00h
  23.           int 21h

  24. show_str: push bp                      ; 在函数入口先保护现场,避免各寄存器的值因调用本函数而被改变
  25.           mov bp,sp
  26.           push ax                     
  27.           push bx
  28.           push cx
  29.           push dx
  30.           push si
  31.           push di
  32.           push ds
  33.           push es
  34.           mov ax,0b800h
  35.           mov es,ax
  36.           mov si , word ptr[bp+06h]    ; 待显示字符串偏移值
  37.           mov bx , word ptr[bp+08h]    ; 行列值
  38.           mov al,bh
  39.           dec al
  40.           mov cl,0a0h
  41.           mul cl
  42.           mov di,ax
  43.           dec bl
  44.           xor bh,bh
  45.           shl bx,1
  46.           add di,bx                    ; di = 行列值对应的显存偏移
  47.           mov bx, word ptr[bp+04]      ; 颜色
  48.           cld
  49. s1:       lodsb                        ; 从 ds:si 读入1个字符到 al
  50.           or al,al                     ; 是结束标志字符吗
  51.           jz s2                        ; 如果是结束字符就跳走
  52.           stosb                        ; 把 al 存入显存 es:di
  53.           mov al,bl                    ; 把颜色字节交给al
  54.           stosb                        ; 把颜色字节存入显存 es:di  
  55.           jmp short s1                 ; 跳回显示下一个字符
  56. s2:       pop es                       ; 开始恢复现场
  57.           pop ds
  58.           pop di
  59.           pop si
  60.           pop dx
  61.           pop cx
  62.           pop bx
  63.           pop ax
  64.           mov sp,bp
  65.           pop bp
  66.           ret
  67. code ends
  68. end start
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-1 23:07:06 | 显示全部楼层
本帖最后由 monkey__ 于 2021-1-1 23:08 编辑
jackz007 发表于 2021-1-1 21:00
问题出在堆栈不平衡,在用 debug 跟踪时,进入 show_str 时记录 sp 值,在要执行 ret 指令前,再看 ...


谢谢~~~

但是把pop cx 前提好像就没办法正常退出那个假循环了 = = 尴尬

您的代码我试了下没有问题,就是有好多指令我还没学到,嘿嘿,等我再往后学下再来研读~~~

再次感谢~~~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-2 00:02:35 | 显示全部楼层
monkey__ 发表于 2021-1-1 23:07
谢谢~~~

但是把pop cx 前提好像就没办法正常退出那个假循环了 = = 尴尬


        按你的思路把 show_str 改了一下,根本没必要动用堆栈,把本来保存在 cl 中的颜色号转到其它寄存器中就好了。
  1. show_str:mov ax,0b800h
  2.          mov es,ax
  3.          sub dh,1
  4.          mov al,160
  5.          mul dh
  6.          mov di,ax
  7.          sub dl,1
  8.          mov al,2
  9.          mul dl
  10.          add di,ax
  11.          mov al,cl
  12.          xor cx,cx
  13. not_ok:  mov cl,byte ptr [si]
  14.          jcxz ok
  15.          mov byte ptr es:[di],cl
  16.          mov byte ptr es:[di+1],al
  17.          inc si
  18.          inc di
  19.          inc di
  20.          jmp short not_ok
  21. ok:      ret
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-9 07:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表