. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->汇编语言学习交流区
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  奇怪问题,请来指导一下,在线等,哈哈,谢谢了!  [已解决] 回复[ 6次 ]   点击[ 500次 ]  
xianxia
[帖 主]   [ 发表时间:2008-11-06 10:26 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:6
注册日期:2008-10-15 11:11
assume cs:code 

data segment 

   db 'Welcome to masm!',0 

data ends 


stack segment 
         
   db 16 dup(0)         

stack ends 


code segment 


 start: mov dh,8 
        mov dl,3 
        mov cl,5 

        mov ax,data 
        mov ds,ax 
        mov si,0 
        call show_str 

        mov ax,4c00h 
        int 21h 
show_str: 
        mov ax,stack   
        mov ss,ax 
        mov sp,16 

        push dx   行和列的参数入栈 
        push cx   颜色的参数入栈 
        push si   把主程序的寄存器入栈 

        mov bp,sp   bp指向栈顶 
        mov ax,0 
        mov al,160 
        mul byte ptr ss:[bp+5]  行地址大小 
        mov bx,ax    把计算好的行地址大小存入BX寄存器 

        mov ah,0 
        mov al,2 
        mul byte ptr ss:[bp+4]  列地址大小 

        add ax,bx                
        mov di,ax              把行和列地址的偏移地址存入DI寄存器 
        mov ax,0b800h 
        mov es,ax             显存地址 

        mov si,0 
 cycle: mov ch,0              
        mov cl,ds:[si]          取字符 
        jcxz ok 
        mov es:[di],cl        送到显存 
        mov ch,ss:[bp+2]       取颜色 
        mov es:[di+1],ch        送显存 
        inc si 
        add di,2            循环进行 

        jmp short cycle 

    ok: pop si              当最后一个字符为“0”的时候返回 
        pop cx               并返回相关的寄存器     
        pop dx 
     
        ret 

code ends 

end start 

以上是我的源程序,名字叫prac10,故执行程序为prac10.exe。 
现象1:用DEBUG调试,载入程序,然后用 第一次g cd21命令,可以显示;还是在DEBUG界面,第二次用 
g cd21命令,不能正常显示?我想这是正常的,因为程序执行过一次,一定要重新载入才可以执行,但不是很确定自己的解释对不对? 

现象2:在CMD界面,直接输入prac10.exe,显示NTVDM CPU遇到无效的指令,CS:059a,ip:97c8,0P:65 63 69 66 69 选择“关闭”终止应用程序。 

对现象2的简单调试的结果:一定要先用DEBUG载入程序,然后才能直接在CMD界面下使用parc10.exe;并且只能输入prac10.exe 一次,如果再次prac10.exe会出现现象2的情况。 

以上2个现象请帮忙解释一下,特别是现象2,是我程序出错了?还是?谢谢,各位了!
mouse
[第1楼]   [ 回复时间:2008-11-06 10:46 ]   [引用]   [回复]   [ top ] 
荣誉值:472
信誉值:12
注册日期:2007-10-16 15:34
已经给你回复了
http://www.asmedu.net/bbs/pasteinfo.jsp?part=1&level=book&kind=1011&qkSg=2&qID=26359

是栈的设置问题,子程序没有正常返回导致程序无法正常结束。
crazyman
[第2楼]   [ 回复时间:2008-11-06 10:47 ]   [引用]   [回复]   [ top ] 
荣誉值:152
信誉值:3
注册日期:2008-01-24 21:26
现象1:用DEBUG调试,载入程序,然后用 第一次g cd21命令,可以显示;还是在DEBUG界面,第二次用  
g cd21命令,不能正常显示?我想这是正常的,因为程序执行过一次,一定要重新载入才可以执行,但不是很确定自己的解释对不对?
--------------------------------------
g 命令是从当前地址执行到你给定的地址出。所以,第一次执行后,当前地址已经不再是程序的起始地址了,所以,在进行g命令就有问题了。
crazyman
[第3楼]   [ 回复时间:2008-11-06 10:55 ]   [引用]   [回复]   [ top ] 
荣誉值:152
信誉值:3
注册日期:2008-01-24 21:26
对现象2的简单调试的结果:一定要先用DEBUG载入程序,然后才能直接在CMD界面下使用parc10.exe;并且只能输入prac10.exe 一次,如果再次prac10.exe会出现现象2的情况。 
------------------------
你的程序直接运行有问题,说明程序有错误的地方。mouse已经指出了,就是定位栈内数据造成的。call指令要push cs ,push ip,这时候用到的是默认的栈,而进入你的子程序后,你对当前栈进行了更改,之前call指令存cs,ip的栈就不是你指定的这个栈了,而在子程序结束后的ret是从当前栈中取数据重新赋值cs,ip的,那么就造成了子程序退出的时候cs,ip的值就不是你call的时候保存的cs,ip的值了,那么指向的指令也将是不可预知的,所以,运行错误很正常。
栈操作的时候一定要多个心眼。
crazyman
[第4楼]   [ 回复时间:2008-11-06 10:57 ]   [引用]   [回复]   [ top ] 
荣誉值:152
信誉值:3
注册日期:2008-01-24 21:26
mouse的方法能够解决你的问题,还有一个方法就是在修改ss之前push ss,在子程序ret指令之前在pop ss,这样就能保证你子程序的正确进入和退出了。
注意程序指令的定位,这在debug调试的时候是一个很重要的信息。
xianxia
[第5楼]   [ 回复时间:2008-11-06 18:58 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:6
注册日期:2008-10-15 11:11
呵呵,mouse,早上的时候没有看到。。。!THANK YOU,mouse and crazyman!
xianxia
[第6楼]   [ 回复时间:2008-11-06 18:59 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:6
注册日期:2008-10-15 11:11
此贴由 贴主 于 [ 2008-11-06 18:59 ] 结贴。 结贴原因:问题已解决
得分情况: 2楼(crazyman):10分  
此问题已结贴!
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved