. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  课程设计1,怎么显示有点不正确?  [待解决] 回复[ 2次 ]   点击[ 772次 ]  
sunshine
[帖 主]   [ 发表时间:2007-06-26 15:38 ]   [引用]   [回复]   [ top ] 
荣誉值:106
信誉值:0
注册日期:2007-06-26 15:10
下面是我的代码
assume cs:codesg

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,8826
        dw 11542,14430,15257,17800
data ends

str0 segment
        db 28 dup (0)
str0 ends


codesg segment
start:  mov ax,data
        mov es,ax         ;  es全局变量下同
        mov ax,str0
        mov ds,ax;ds
        mov dx,0;dx
        mov cx,21          ;cx循环21次,每次显示一行
        mov si,0;si
        mov di,0;di
        mov bp,16
s:      push cx
        push dx

        mov ax,es:[si]
        mov dx,es:2[si]         ;dx!o(o为全局变量已保护,下同)
        mov [di],ax
        mov 2[di],dx


        push si     
        mov ax,es:168[bp]
        mov dx,0                   ;dx!o
        mov si,16                  ;si!o
        call dtoc
        pop si


        mov ax,es:84[si]
        mov dx,es:86[si]           ;dx!o   
        push si
        mov si,5                   ;si!o
        call dtoc
        mov bx,es:168[bp]                
        div bx                       ;使用上方AX,DX
        mov dx,0
        mov si,22;si!o
        call dtoc
        pop si

        pop dx
       
        push si
        mov dl,0
        mov cl,2                ;cx!o
        mov si,0                ;si!o
        call show_str
        mov dl,9
        mov si,5                ;si!o
        call show_str
        mov dl,23
        mov si,16               ;si!o
        call show_str
        mov dl,38
        mov si,22               ;si!o
        call show_str
        pop si

        pop cx

        inc dh
        add si,4
        add bp,2
        loop s

        mov ax,4c00h
        int 21h

dtoc:           push ax       ;将数据转换为字符串,dd型数据
                push bx
                push cx
                push dx
                push di
                push si

                mov di,0
             
        step1:  mov cx,dx
                jcxz lowbyte
                mov bx,10
                call divdw
                push bx
                inc di
                jmp short step1
        lowbyte:
                mov bx,10
                call divdw
                push bx
                inc di
                mov cx,ax
                jcxz di2cx
                jmp short lowbyte
        di2cx:  mov cx,di

        step2:  pop bx
                add bx,30h
                mov [si],bx
                inc si
                loop step2
           
        finish: pop si
                pop di
                pop dx
                pop cx
                pop bx
                pop ax
                ret

divdw:               ;除法子程序,防溢出
        push cx 
        push ax
        mov ax,dx
        mov dx,0
        div bx
        mov cx,ax
        pop ax
        div bx
        mov bx,dx
        mov dx,cx

        pop cx
        ret

show_str:       push ax              ;显示字符串,字符串后以数据0结尾
                push bx
                push cx
                push dx
                push es
                push si
                push di

                mov al,0a0h
                mul dh
                mov dh,0
                add dl,dl
                add ax,dx
                mov di,ax
                mov ax,0b800h
                mov es,ax
                mov bl,cl

        display:mov cl,[si]
                mov ch,0
                jcxz fin
                mov es:[di],cl
                mov es:1[di],bl
                add di,2
                inc si
                jmp short display

        fin:    pop di
                pop si
                pop es
                pop dx
                pop cx
                pop bx
                pop ax
                ret
codesg ends
end start
    可否帮我修改一下,  有什么错误给我请指正,  我不胜感激!
beerman
[第1楼]   [ 回复时间:2007-07-24 09:01 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2007-07-23 17:31
回复:[贴 主]
------------------
==============================================================================
第10章  课程设计1
==============================================================================
assume cs:codesg,ds:data

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 16 dup (0)
table ends

codesg segment
  start:   
          mov ax,data
          mov ss,ax            ;ss指向数据
          mov bp,0
          mov bx,0
         
          ;21行循环年份
          mov cx,21            
     Row1:push cx
          push bp
          mov si,bp           ;把年份首地址存入si中传给show_year          
          call show_year           
          inc bx              ;当前行数存入bx中,传给show_year
          pop bp         
          add bp,4             ;下一个年份首地址,每个年份占4个字节         
          pop cx
          loop Row1


           ;21行循环收入
           mov si,0            ;当前行计数
           mov bp,0
           mov di,0
           mov cx,21
      Row2:push cx             ;按顺序压入本段变量
           push bp
           push di
           mov ax,[bp+54h+di]  ;循环写入收入。数据启始地址+收入偏移量+每次移动2个字节
           mov dx,[bp+54h+di+2]
           call dtoc           ;转换数字为ascll码
           mov dh,4          ;设置显示初始值
           mov dl,13
           mov cl,2
           call show_str       ;显示字符串
           inc si              ;循环到第几行了
           pop di
           add di,4
           pop bp
           pop cx
           loop Row2
 

           ;21行循环雇员数
           mov si,0            ;当前行计数
           mov bp,0
           mov di,0
           mov cx,21
      Row3:push cx             ;按顺序压入本段变量
           push bp
           push di
           mov ax,[bp+00a8h+di]  ;循环写入收入。数据启始地址+收入偏移量+每次移动2个字节
           mov dx,0000h
           call dtoc           ;转换数字为ascll码
           mov dh,4          ;设置显示初始值
           mov dl,23
           mov cl,2
           call show_str       ;显示字符串
           inc si              ;循环到第几行了
           pop di
           add di,2
           pop bp
           pop cx
           loop Row3     
           

           ;21行循环人均收入
           mov si,0            ;当前行计数
           mov bp,0
           mov di,0
           mov cx,21
      Row4:push cx             ;按顺序压入本段变量
           push bp
           mov ax,[bp+54h]     ;被除数低16位
           mov dx,[bp+54h+2]   ;被除数高16位
           push di
           div word ptr ss:[00a8h+di]    ;收入/雇员数=人均收入,结果存在ax中
           mov dx,0000h
           call dtoc           ;转换数字为ascll码
           mov dh,4           ;设置显示初始值
           mov dl,33
           mov cl,2
           call show_str       ;显示字符串
           inc si              ;循环到第几行了
           pop di
           add di,2            ;di加2是为了循环雇员数
           pop bp
           add bp,4
           pop cx
           loop Row4

         mov ax,4c00h
         int 21h


           
;显示年份(当前行数用bx)
show_year: mov dh,4
           mov dl,3
           mov cl,2
           mov ax,0b800h
           mov es,ax              
           mov al,160
           mul dh            ;每行160*8行
           mov bp,ax
            
           mov al,2          ;3列*每列2个字节
           mul dl 
           add bp,ax
                    
           ;mov bp,160*8+3*2 ;每行160*8行+3列*每列2个字节,160*8+3*2=0506h
           
           mov ax,160
           mul bx              ;bx是当前行数
           mov dl,cl           ;保护cl,因为cx要循环
           mov di,ax           ;乘法的结果ax,得到当前行偏移量存入di中
           mov cx,4            ;年份是4个字符
     while:mov ax,ss:[si]      ;si是年份在data中的首地址
           mov es:[bp+di],ax 
           mov es:[bp+di+1],dl ;是颜色
           inc si
           add di,2
           loop while

           ret

;转换数字为ascll码
    dtoc:mov cx,0
         push cx      ;先压入一个0作为是否到结尾的判断。
   dtoc2:mov cx,0ah   ;16位高位在dx,低位在ax中已经放好了。除数放在cx中
         call divdw   ;调用防止溢出除法程序。
         add cx,30h   ;余数加30h变成ascll码
         push cx      ;把余数压入
         mov cx,ax    ;配合jmp使用的,判断商是否为0
         jcxz return        
         jmp short dtoc2
  return:mov ax,table ;出栈字符串存放的位置
         mov ds,ax    ;ds指向table段
         mov di,0     ;di指向table首地址
  chang2:pop ax
         mov [di],ax
         inc di
         mov cx,ax
         jcxz ok2
         jmp short chang2
         
     ok2:mov di,0       ;ds:si指向字符传首位,下一步为显示做准备
         ret

;显示字符串(当前行数用si)
show_str:  mov ax,0b800h
           mov es,ax              
           mov al,160
           mul dh            ;每行160*8行
           mov bp,ax
            
           mov al,2          ;3列*每列2个字节
           mul dl 
           add bp,ax
                    
           ;mov bp,160*8+3*2 ;每行160*8行+3列*每列2个字节,160*8+3*2=0506h
           
           
           mov ax,160
           mul si            ;si是当前行数
           mov di,0          ;设置指向字符串首地址
           add bp,ax         ;得到当前行的偏移量
    while2:        
           mov ax,[di]       ;段地址还是ds
           mov es:[bp+di],ax
           mov al,cl         ;保存cl颜色,因为下面要用cx判断
           mov es:[bp+di+1],cl
           mov cl,[di]
           mov ch,0
           jcxz ok
           inc di
           add bp,1          ;每一个字符向后挪2个字节,其中一个保存颜色。
           mov cl,al         ;还原颜色

           jmp short while2
        ok:ret
           

 ;防止除法溢出
 divdw:
       ;对高16位000fh进行除法
       mov di,ax    ;保存低16位ax中的被除数
       mov ax,dx    ;设被除数低16位为000fh
       mov dx,0000h ;设被除数高16位为0
       div cx    
       mov bp,dx    ;保存高16位运算余数到bp中
       mov bx,1000h ;把65536拆分成1000和10,对ax进行高16位商的乘法
       mul bx
       mov bx,0010h
       mul bx       ;低16位默认保存在ax中;高16位默认保存在dx中。
       push ax      ;压入高16位商的乘法结果的低16位  
       push dx      ;压入高16位商的乘法结果的高16位 


       ;对低16位进行除法运算
       mov ax,bp    ;高16位除法的余数,dx中是余数
       mov bx,1000h ;把65536拆分成1000和10,进行高16位余数乘法
       mul bx
       mov bx,0010h
       mul bx       ;低16位默认保存在ax中;高16位默认保存在dx中。
       add ax,di    ;把高16位余数的乘法加上低16位
       div cx       ;相加的结果除以cx,算出低16位结果
       mov cx,dx
     
      
 
       ;合并结果。高16位结果在dx中;低16位结果在ax中;余数在cx中     
       pop dx;弹出高16位结果dx
       pop bx ;弹出低16位结果ax
       add ax,bx
       ret

codesg ends
end start
sunshine
[第2楼]   [ 回复时间:2007-07-24 10:31 ]   [引用]   [回复]   [ top ] 
荣誉值:106
信誉值:0
注册日期:2007-06-26 15:10
哎呀,都一个月了还有人来指教,太感谢了!相当感谢。呵呵
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved