. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  实验10-3编写的程序找不到错误,请教大家(有详细说明)  [已解决] 回复[ 6次 ]   点击[ 599次 ]  
ztf770710
[帖 主]   [ 发表时间:2010-04-27 15:26 ]   [引用]   [回复]   [ top ] 
荣誉值:4
信誉值:2
注册日期:2008-01-16 11:01
显示字符串和除法溢出2个子程序都经过验证的。程序如下:
assume cs:code

data segment
  db 10 dup (0)
data ends

stack segment
  dw 32 dup (0)
stack ends

code segment
start: mov ax,data
       mov ds,ax        ;设置ASC码存放空间
       mov ax,stack
       mov ss,ax
       mov sp,64        ;设置栈段
       mov si,0         ;设置首地址
       mov ax,12666
       mov dx,0         ;将数值的低16位送入ax,高16位送入dx,调用子程序转换为ASC码
       call dtoc        ;调用转换为ASC码子程序
       mov dh,8         ;输入行号
       mov dl,3         ;输入列号
       mov cl,2         ;输入颜色        
       call show_str    ;调用显示字符串子程序

       mov ax,4c00h
       int 21h

dtoc:  push ax
       push bx
       push cx
       push dx
       push si
       push ds          ;将子程序用到的寄存器入栈
       mov bx,0         ;设置计数器

  d0:  mov cx,10        ;除数为10
       call divdw       ;调用避免除法溢出子程序,商的高16位在dx中,低16位在ax中,余数在cx中
       add cx,30h       ;余数加30h,变为ASC码
       push cx          ;将余数ASC码入栈
       inc bx           ;计数器加1
       mov cx,dx        ;将商的的高16位移入cx
       jcxz d1          ;如果(cx)=0,转移到d1处;如果不是0,向下执行
       jmp near ptr d0  ;转移到d0处,继续做除法 

  d1:  mov cx,ax        ;将商的的低16位移入cx   
       jcxz ak          ;如果(cx)=0,转移到ak处;如果不是0,向下执行         
       jmp near ptr d0  ;转移到d0处,继续做除法

  ak:  mov cx,bx        ;将计数器的值存入cx

  bk:  pop ax           ;最后的余数ASC码出栈
       mov [si],al      ;将余数ASC码存入ds:si处
       inc si           ;si加1
       loop bk          ;如果(cx)=0,向下执行;如果不是0,转移到bk处,循环将栈中的余数ASC出栈
       mov [si],0       ;设置ASC码结束符,显示字符串子程序根据此符号判断字符串是否结束

       pop ds
       pop si
       pop dx
       pop cx
       pop bx
       pop ax           ;将子程序用到的寄存器出栈
       ret 

show_str: push es
          push ds
          push si
          push ax
          push bx
          push dx
          push cx          ;将子程序用到的寄存器入栈      

          mov al,10        
          mul dh
          mov bx,0b800h    
          add ax,bx        
          mov es,ax        ;设置行段地址
          mov bh,0
          mov bl,dl
          add bx,bx
          sub bx,2         ;设置第一个字符的偏移地址(列地址)
       s: mov cl,[si]
          mov ch,0
          jcxz ok          ;如果(cx)=0,转移到标号处;如果不是0,向下执行
          pop cx           ;将子程序中要用的寄存器内的内容出栈
          push cx          ;将子程序要用到的寄存器入栈          
          mov dl,[si]      
          mov es:[bx],dl   ;将字符的ASCII码写入显存
          mov es:[bx+1],cl ;将字符的属性写入显存
          inc si
          add bx,2         ;下一个字符
          jmp near ptr s   ;跳转到s处执行

      ok: pop cx
          pop dx
          pop bx
          pop ax
          pop si           
          pop ds
          pop es           ;将子程序用到的寄存器出栈
          ret

divdw: push bx
       push bp
       mov bp,ax         ;将被除数的低16位存入bp
       mov ax,dx         ;将被除数X得高16位存入ax,作为H的低16位
       mov dx,0          ;将dx置0,作为H的高16位
       div cx            ;H/N
       mov bx,ax         ;将H/N的商存入bx
       mov ax,bp         ;将被除数的低16位存入ax
       div cx            ;[rem(H/N)*65536+L]/N,商(低16位)在ax中
       mov cx,dx         ;将余数存入cx
       mov dx,bx         ;将高16位存入dx
       pop bp
       pop bx
       ret

code ends 
end start       
    没法masm,请问高手问题在哪里?
versaariel
[第1楼]   [ 回复时间:2010-04-28 09:08 ]   [引用]   [回复]   [ top ] 
荣誉值:62
信誉值:0
注册日期:2009-12-03 13:14
google下个masm很快的,加下环境变量就能用了
mov [si],0       ;设置ASC码结束符,显示字符串子程序根据此符号判断字符串是否结束 
mov [si],0这句编译报Operand must have size->mov byte ptr[si],0
其他逻辑上的就自己检查下吧^-^
ztf770710
[第2楼]   [ 回复时间:2010-04-28 13:41 ]   [引用]   [回复]   [ top ] 
荣誉值:4
信誉值:2
注册日期:2008-01-16 11:01
楼上兄弟指出的确实是个错误。我不是没有masm,而是用masm汇编源程序后,如果源程序有错误,就不会产生obj文件,没有任何说明,直接退出masm。请问如何看到编译报错?
versaariel
[第3楼]   [ 回复时间:2010-04-28 16:10 ]   [引用]   [回复]   [ top ] 
荣誉值:62
信誉值:0
注册日期:2009-12-03 13:14
编译器错误就在命令行下方,不要说你看不懂E文=.=
Operand must have size就是masm5.0报的
ztf770710
[第4楼]   [ 回复时间:2010-04-29 09:02 ]   [引用]   [回复]   [ top ] 
荣誉值:4
信誉值:2
注册日期:2008-01-16 11:01
看不到任何东西。我运行masm.exe文件,进入dos环境,输入路径:…\...\...\*.asm;,如果程序正确,会生成*.obj文件;如果程序不正确,则dos屏幕一闪就不见了,也不会生成任何文件。故程序有错误,我看不到任何错误提示。
   非常感激versaariel。将mov [si],0改成mov ax,0 / mov [si],ax,程序顺利通过。
   另外,我觉得如果需要显示的数字超过65536,则程序要改动2处:
第一处:
data segment
  db 10 dup (0)
  dd 5937000  ;新加入的句子,为要显示的数字
data ends
第二处:将
mov ax,12666
mov dx,0      ;将数值的低16位送入ax,高16位送入dx,调用子程序转换为ASC码
改成:
Mov ax,ds:[10]  ;将数值的低16位送入ax
Mov dx,ds:[12]  ;将数值的高16位送入dx
则超过65536的数字也能顺利显示了。

   还有个问题,如果程序改成如下:
data segment
  db 10 dup (0)
data ends
data2 segment
  dd 5937000
data2 ends
.
.
.
Mov ax,data
Mov ds,ax
Mov ax,ds:[?]
Mov dx,ds:[?+2]
那么,?处填的数字是什么。我试过,填10是错误的。
versaariel
[第5楼]   [ 回复时间:2010-04-29 11:12 ]   [引用]   [回复]   [ top ] 
荣誉值:62
信誉值:0
注册日期:2009-12-03 13:14
1.恩,确实试了下你的方法,好象你那样看不到编译结果,原因就不说了,以后你会知道^-^
2.
--------------------引用-------------------------------
我运行masm.exe文件,进入dos环境,输入路径:…\...\...\*.asm
-------------------------------------------------------
换个方法,论坛里有教过的
我的电脑->属性->高级->环境变量->用户变量中找到path加入masm.exe的路径,就可以在任意路径下编译文件了.比如我加的是;E:\Program Files\masm5.0(前面那个;一定要加)
编译的时候:win+r->cmd->定位到你程序文件(test.asm)的路径,不要说你不会用cd命令,
最后masm test.asm就行了
3.有时间多看看论坛里的旧帖子,都很好的^-^
ztf770710
[第6楼]   [ 回复时间:2010-05-10 13:59 ]   [引用]   [回复]   [ top ] 
荣誉值:4
信誉值:2
注册日期:2008-01-16 11:01
此贴由 贴主 于 [ 2010-05-10 13:59 ] 结贴。 结贴原因:问题已解决
得分情况: 1楼(versaariel):5分   5楼(versaariel):5分  
此问题已结贴!
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved