. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  10.1超奇怪现象,请各位朋友来参与,同时请高手指点,谢谢了!  [已解决] 回复[ 3次 ]   点击[ 349次 ]  
xianxia
[帖 主]   [ 发表时间:2008-11-05 16:07 ]   [引用]   [回复]   [ 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:43 ]   [引用]   [回复]   [ top ] 
荣誉值:472
信誉值:12
注册日期:2007-10-16 15:34
我用debug跟踪发现,子程序show_str的最后一条指令ret执行后并没有返回主程序的返回指令处执行,而是跳到了别的地方。--这也就是程序出错的原因。

而ret的指令做的是pop操作,所以问题出在栈上。

        mov ax,stack   
        mov ss,ax 
        mov sp,16 
--------------------把这三条指令移动到程序初始化开始,即call指令前。

call指令也用到了栈。

详细看汇编语言的第十章。楼主用bp读数据,不错^_^
xianxia
[第2楼]   [ 回复时间:2008-11-06 11:51 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:6
注册日期:2008-10-15 11:11
呵呵,mouse,!thank you!问题解决,还是我太浮澡了,跟踪看过,但没有跟踪到ret执令,就用g cd21命令了!
仔细对比了  mov ax,stack    
          mov ss,ax  
          mov sp,16  

这三条指令在call在程序初始化之前和之后的区别,主要的原因是栈空间的地址不一样的。。。!即如果把以上3个命令放在调用CALL之前,那程序会把IP压到的FFFE这个栈,而我误以为是把IP放到了0E地址这个里面,导致返回的时候,不能返回。
xianxia
[第3楼]   [ 回复时间:2008-11-06 18:59 ]   [引用]   [回复]   [ top ] 
荣誉值:6
信誉值:6
注册日期:2008-10-15 11:11
此贴由 贴主 于 [ 2008-11-06 18:59 ] 结贴。 结贴原因:问题已解决
得分情况: 1楼(mouse):4分  
此问题已结贴!
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved