. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  课程设计1,请各位帮忙看一下哪里出了问题  [待解决] 回复[ 3次 ]   点击[ 300次 ]  
tp7309
[帖 主]   [ 发表时间:2011-05-23 09:50 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2011-05-16 20:38
改了很多遍调了很久还是不知道问题出在哪,光清屏不显示,上来求各位解惑。
代码如下:
assume cs:code
data segment 
    db '1975','1976','1977','1978','1979','1980','1981','1982','1983' 
    db '1984','1985','1986','1987','1988','1989','1990','1991','1992' 
    db '1993','1994','1995' 

    dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514 
    dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000 

    dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226 
    dw 11542,14430,15257,17800 

data ends 

table segment
   db 21 dup('year summ ne ?? ')
table ends
display segment
    db 11 dup(0)     ;数值显示时存放字符的栈(32位字节最高10个二进制位,再加一个表结束的字符0)
display ends
code segment
start:mov ax,data
          mov ds,ax
          mov si,0        ;新增变量.年份长度4字节,收入长度4字节,雇员数2字节 
          mov bx,0        ;4字节的属性用si做增量,2字节的属性用bx做增量.   
          mov ax,table
          mov es,ax
          mov di,0      ;es:[di]指向table区,ds:[si]指向源数据,es:[di]指向目标数据
          mov cx,21     ;循环21次
;通过21次循环,完成将data段中的数据按照要求的格式写入到table段中. 
;这是实验7应该实现的要求.
s:push [si]
  push [si].2
  pop es:[di].2
  pop es:[di]
  push [si].84
  push [si].86
  pop es:[di].7h
  pop es:[di].5h
  push [bx].168
  pop es:[di].0ah
  mov ax,es:[di].5h    ;计算人均收入并写入相应的table段中.
  mov dx,es:[di].7h
  div word ptr es:[di].0ah
  mov es:[di].0dh,ax
  add si,4
  add bx,2
  add di,10h
  loop s
call cls      ;调用子程序cls,实现要显示的区域清屏
mov ax,table   ;实现将table段中的数据显示到屏幕上. 
mov es,ax
mov di,0        ;es:[di]指向目标数据
mov ax,display   
mov ds,ax
mov si,0        ;ds:[si]要显示的数据
mov dh,2        ;初始化参数
mov dl,3
mov bh,dl       ;保存列信息
mov cl,2
mov bl,cl       ;保存颜色信息
call display_data   ;显示数据
mov ax,4c00h
int 21h
;子程序实现清除屏幕,无返回值。 
cls: 
    push ax  
    push ds 
    push si 
    push cx 
    mov ax,0b800h 
    mov ds,ax 
    mov si,140h

    mov cx,1680 
cls_s:mov word ptr ds:[si],0700h 
    add si,2 
    loop cls_s 

    pop cx 
    pop si 
    pop ds 
    pop ax 
    ret         

display_data:push ax
                         push cx
                         push dx
                         push si
                         push di
                         mov cx,21
disdata0:push cx
                push es:[di]    ;显示"年份"列
                push es:[di].2
                pop [si].2
                pop [si]
                mov byte ptr [si].4h,0
                mov cl,bl
                call show_str

                mov ax,es:[di].5h     ;显示"收入"列
                mov dx,es:[di].7h
                mov si,0
                call dtoc
                add dl,10
                mov cl,bl
                call show_str

                mov ax,es:[di].0ah     ;显示“雇员数”列
                mov dx,0
                call dtoc
                add dl,10
                mov cl,bl
                call show_str

                mov ax,es:[di].0dh     ;显示“人均收入”列
                mov dx,0
                call dtoc
                add dl,10
                mov cl,bl
                call show_str

                inc dh
                mov dl,bh
                pop cx
                loop disdata0
                pop di
                pop si
                pop dx
                pop cx
                pop ax
                ret
;名称:show_str
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0~24);
;      (dl)=列号(取值范围0~79);
;      (cl)=颜色;
;      ds:si指向字符串的首地址。
;返回:无。
show_str:push ax
     push bx
     push cx
     push es
     push si
     mov ax,0b800h
     mov es,ax
     mov ax,160
     mul dh
     mov bx,ax     ;bx=160*dh
     mov ax,2
     mul dl        ;ax=dl*2
     add bx,ax     ;mov bx,(160*dh+dl*2)设置es:bx指向显存首地址
     mov al,cl     ;把颜色cl赋值al
     mov cl,0
show0:mov ch,[si]
     jcxz show1    ;(ds:si)=0时,转到show1执行
     mov es:[bx],ch
     mov es:[bx].1,al
     inc si        ;ds:si指向下一个字符地址
     add bx,2      ;es:bx指向下一个显存地址
     jmp show0
show1:pop si
      pop es
      pop cx
      pop bx
      pop ax
     ret
;名称:divdw
;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
;参数:(ax)=dword型数据的低16位;
;      (dx)=dword型数据的高16位;
;      (cx)=除数。
;返回:(dx)=结果的高16位;
;      (ax)=结果的低16位;
;      (cx)=余数。
divdw:push si
     push ax
     mov ax,dx
     mov dx,0
     div cx        ;被除数的高位/cx,高位在ax,余数在dx
     mov si,ax
     pop ax 
     div cx        ;(被除数高位的商+低位)/cx,高位在ax,余数在dx
     mov cx,dx     ;余数入cx
     mov dx,si     ;高位的商入dx
     pop si
     ret
;将dword型数据转变为表示十进制的字符串,字符串以0为结尾符。
dtoc:push ax
     push bx
     push cx
     push dx
     push si
     push di
     mov di,0
d20: mov cx,10     ;除数为10
     call divdw
     add cx,30h    ;余数+30h,转为字符
     push cx       ;字符入栈
     inc di        ;记录字符个数
     mov cx,ax 
     jcxz d21      ;低位商=0时,转到d21检测高位商
     jmp d20
d21: mov cx,dx
     jcxz d22      ;高低位商全=0时,转到d22执行
     jmp d20
d22: mov cx,di
d23: pop ax        ;字符出栈
     mov [si],al
     inc si        ;ds:si指向下一单元
     loop d23
     mov al,0
     mov [si],al   ;设置结尾符0
     pop di
     pop si
     pop dx
     pop cx
     pop bx
     pop ax
     ret
code ends
end start
betterpursuel
[第1楼]   [ 回复时间:2011-05-23 21:15 ]   [引用]   [回复]   [ top ] 
荣誉值:8
信誉值:0
注册日期:2010-11-07 17:01
assume cs:code

data segment
    db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
    db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
    db '1993','1994','1995'

    dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
    dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000

    dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
    dw 11542,14430,15257,17800
data ends

table segment
   db 21 dup('year summ ne ?? ')
table ends

display segment
    db 11 dup(0)     ;数值显示时存放字符的栈(32位字节最高10个二进制位,再加一个表结束的字符0)
display ends

code segment
start:    mov ax,data
          mov ds,ax
          mov si,0        ;新增变量.年份长度4字节,收入长度4字节,雇员数2字节
          mov bx,0        ;4字节的属性用si做增量,2字节的属性用bx做增量.

          mov ax,table
          mov es,ax

          mov di,0      ;es:[di]指向table区,ds:[si]指向源数据,es:[di]指向目标数据
          mov cx,21     ;循环21次
;通过21次循环,完成将data段中的数据按照要求的格式写入到table段中.
;这是实验7应该实现的要求.
      s:  push [si]
          push [si].2
          pop es:[di].2
          pop es:[di]

          push [si].84
          push [si].86
          pop es:[di].7h
          pop es:[di].5h

          push [bx].168
          pop es:[di].0ah

          mov ax,es:[di].5h    ;计算人均收入并写入相应的table段中.
          mov dx,es:[di].7h
          div word ptr es:[di].0ah
          mov es:[di].0dh,ax

          add si,4
          add bx,2
          add di,10h
        loop s

        call cls      ;调用子程序cls,实现要显示的区域清屏



        mov ax,table   ;实现将table段中的数据显示到屏幕上.
        mov es,ax
        mov di,0        ;es:[di]指向目标数据

        mov ax,display
        mov ds,ax
        mov si,0        ;ds:[si]要显示的数据

        mov dh,2        ;初始化参数
        mov dl,3
        mov bh,dl       ;保存列信息
        mov cl,2
        mov bl,cl       ;保存颜色信息
        call display_data   ;显示数据


mov ax,4c00h
int 21h


;子程序实现清除屏幕,无返回值。
cls:
    push ax
    push ds
    push si
    push cx
    mov ax,0b800h
    mov ds,ax
    mov si,140h

    mov cx,1680
cls_s:mov word ptr ds:[si],0700h
    add si,2
    loop cls_s

    pop cx
    pop si
    pop ds
    pop ax
    ret


display_data:    push ax
                 push cx
                 push dx
                 push si
                 push di

                mov cx,21
disdata0:       push cx

                push es:[di]          ;显示"年份"列
                push es:[di].2
                pop [si].2
                pop [si]
                mov byte ptr [si].4h,0
                mov cl,bl
                call show_str


                mov ax,es:[di].5h     ;显示"收入"列
                push dx               ;--------------------这是新加的内容
                mov dx,es:[di].7h
                mov si,0
                call dtoc
                pop dx                 ;-------------------这是新加的内容
                add dl,10
                mov cl,bl
                call show_str



                mov ax,es:[di].0ah     ;显示“雇员数”列
                push dx                ;-------------------这是新加的内容
                mov dx,0
                call dtoc
                pop dx                 ;-------------------这是新加的内容
                add dl,10
                mov cl,bl
                call show_str


                mov ax,es:[di].0dh     ;显示“人均收入”列
                push dx                ;---------------------这是新加的内容
                mov dx,0
                call dtoc
                pop dx                ;----------------------这是新加的内容
                add dl,10
                mov cl,bl
                call show_str


                add di,16              ;---------------------这是新加的内容
                inc dh
                mov dl,bh
                pop cx
                loop disdata0


                pop di
                pop si
                pop dx
                pop cx
                pop ax
                ret


;名称:show_str
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0~24);
;      (dl)=列号(取值范围0~79);
;      (cl)=颜色;
;      ds:si指向字符串的首地址。
;返回:无。
show_str:push ax
     push bx
     push cx
     push es
     push si

     mov ax,0b800h
     mov es,ax
     mov ax,160
     mul dh
     mov bx,ax     ;bx=160*dh
     mov ax,2
     mul dl        ;ax=dl*2
     add bx,ax     ;mov bx,(160*dh+dl*2)设置es:bx指向显存首地址
     mov al,cl     ;把颜色cl赋值al
     mov cl,0
show0:mov ch,[si]
     jcxz show1    ;(ds:si)=0时,转到show1执行
     mov es:[bx],ch
     mov es:[bx].1,al
     inc si        ;ds:si指向下一个字符地址
     add bx,2      ;es:bx指向下一个显存地址
     jmp show0
show1:
      pop si
      pop es
      pop cx
      pop bx
      pop ax
     ret


;名称:divdw
;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
;参数:(ax)=dword型数据的低16位;
;      (dx)=dword型数据的高16位;
;      (cx)=除数。
;返回:(dx)=结果的高16位;
;      (ax)=结果的低16位;
;      (cx)=余数。
divdw:push si
     push ax
     mov ax,dx
     mov dx,0
     div cx        ;被除数的高位/cx,高位在ax,余数在dx
     mov si,ax
     pop ax
     div cx        ;(被除数高位的商+低位)/cx,高位在ax,余数在dx
     mov cx,dx     ;余数入cx
     mov dx,si     ;高位的商入dx
     pop si
     ret


;将dword型数据转变为表示十进制的字符串,字符串以0为结尾符。
dtoc:push ax
     push bx
     push cx
     push dx
     push si
     push di

     mov di,0
d20: mov cx,10     ;除数为10
     call divdw
     add cx,30h    ;余数+30h,转为字符
     push cx       ;字符入栈
     inc di        ;记录字符个数
     mov cx,ax
     jcxz d21      ;低位商=0时,转到d21检测高位商
     jmp d20
d21: mov cx,dx
     jcxz d22      ;高低位商全=0时,转到d22执行
     jmp d20
d22: mov cx,di
d23: pop ax        ;字符出栈
     mov [si],al
     inc si        ;ds:si指向下一单元
     loop d23
     mov al,0
     mov [si],al   ;设置结尾符0

     pop di
     pop si
     pop dx
     pop cx
     pop bx
     pop ax
     ret


code ends
end start
betterpursuel
[第2楼]   [ 回复时间:2011-05-23 21:22 ]   [引用]   [回复]   [ top ] 
荣誉值:8
信誉值:0
注册日期:2010-11-07 17:01
1楼是已经改对的程序,已经可以出结果了,你写的程序只有这个display_data函数错了,我只是在其中加了7句话,程序就对了,在调用小函数时,请注意保存你的行dh列dl信息所以要保护dx的值,你确没有去保护;你仔细看看以下的程序:
                mov ax,es:[di].0ah     ;显示“雇员数”列 
                push dx                ;-------------------这是新加的内容 
                mov dx,0 
                call dtoc 
                pop dx                 ;-------------------这是新加的内容 
                add dl,10 
                mov cl,bl 
                call show_str 


                mov ax,es:[di].0dh     ;显示“人均收入”列 
                push dx                ;---------------------这是新加的内容 
                mov dx,0 
                call dtoc 
                pop dx                ;----------------------这是新加的内容 
                add dl,10 
                mov cl,bl 
                call show_str 


                add di,16              ;---------------------这是新加的内容 
                  inc dh 
                mov dl,bh 
                pop cx 
                loop disdata0
tp7309
[第3楼]   [ 回复时间:2011-05-26 11:51 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2011-05-16 20:38
谢谢楼上,呼终于找到问题所在了。郁闷怎么就把dx给忘了.
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved