汇编网首页登录博客注册
sissim的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
好友圈
友情链接

[2010-02-11 00:52] 推荐博文 课程设计1

放了这么久,真不应该。

一晚上,五个小时的时间,终于……
做这个课程设计,完全应用了自顶向下的编程方法。
这样思路很清晰。
这中间,发现了很多问题。
最主要的一个就是编写子程序时,对寄存器的保护做得不够,
以致于子程序不能很放心的直接拿来用。
很多时间,都是在跟踪哪个寄存器在哪个子程序中发生了改变。

        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 
        dd      5937000 
        dw      3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635 
        dw      8226,11542,14430,15257,17800 
data    ends 
table   segment 
        db      21 dup('year summ ne ?? ') 
strd    db        8 dup(0)
strdn   db        8 dup(0)
table   ends 
codesg  segment 
start:  
        mov     ax,data 
        mov     ds,ax 
        mov     ax,table 
        mov     ss,ax 

        mov     cx,21 
        mov     bx,0 
        mov     bp,0 
        mov     di,168 

s:      mov     ax,[bx] 
        mov     [bp],ax 
        mov     ax,[bx+2] 
        mov     [bp+2],ax 

        mov     ax,[bx+84] 
        mov     [bp+5],ax 
        mov     dx,[bx+86] 
        mov     [bp+7],dx 

        mov     si,[di] 
        mov     [bp+10],si 
        div     si 
        mov     [bp+0dh],ax 

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

;以上是创建table段数据,直接复制实验七的程序。


        mov        ax,table
        mov        ds,ax
        mov        cx,21
        mov        bx,0
        mov        dh,5
next:   mov        dl,1
        mov        si,bx
        mov        4[bx],byte ptr 0 ;把空格替换为0
        push        cx
        mov        cx,71h                ;颜色
        call        show_str        ;显示年份
        
        mov        ax,5[bx]
        push        dx
        mov        dx,7[bx]
        mov        si,offset strd        ;将转换成的字符串存放在strd中
        call        dtoc
        pop        dx
        mov        dl,12
        mov        cx,71h
        call        show_str        ;显示收入

        push        dx
        mov        dx,0
        mov        ax,0ah[bx]
        mov        si,offset strd
        call        dtoc
        pop        dx
        mov        dl,23
        mov        cx,71h
        call        show_str        ;显示雇员数

        push        dx
        mov        dx,0
        mov        ax,0dh[bx]
        mov        si,offset strd
        call        dtoc
        pop        dx
        mov        dl,34
        mov        cx,71h
        call        show_str        ;显示人均收入
        pop        cx
        
        inc        dh
        add        bx,10h
        loop        next
        
        mov        ax,4c00h
        int        21h


show_str: 
        push        ax 
        push        bx 
        push        cx 
        push        dx 
        push        si 
        push        es 
        dec        dh                ;行号减一 
        mov     al,0a0h 
        mul     dh                ;0a0h*(行号-1) 
        mov     dh,0 
        dec     dl 
        add     dx,dx                ;2*(列号-1) 
        add     ax,dx                ;0a0h*(行号-1)+2*(列号-1) 
        mov     bx,ax 
        mov     ch,0                ;ch清零,为cx进栈(颜色)做准备 
        mov     ax,0b800h 
        mov     es,ax                ;显存段地址 
s1:     push    cx                ;颜色进栈 
        mov     cl,[si]                ;取出一个字符 
        jcxz    ok                ;是零则返回 
        mov     es:[bx],cl        ;不是零,放显存相应单元 
        inc     bx 
        pop     cx                ;取回颜色 
        mov     es:[bx],cl        ;存颜色 
        inc     bx 
        inc     si 
        jmp     short s1                ;修改指针并循环 
ok:     pop     cx      ;返回前,将刚才进栈的cx出栈,使栈顶指针指向返回地址 
        pop        es 
        pop        si 
        pop        dx 
        pop        cx 
        pop        bx 
        pop        ax 
        ret 

;以上为显示以零结尾的字符串,直接复制实验10.1

dtoc:        
s2:     mov        cx,10
        call        divdw
        or        cl,30h
        mov        [si],cl
        and        dx,dx
        jnz        n1
        and        ax,ax
        jz        nixu
n1:     inc        si
        jmp        s2
nixu:   mov        di,offset strdn
        call        clrdi
n2:     cmp        si,offset strd
        jb        over
        mov        al,[si]
        mov        [di],al
        inc        di
        dec        si
        jmp        n2
over:   mov        si,offset strdn
        ret
;这个变化较大,逆序合并到里面了。

divdw:  push    bx
        mov     bx,ax        ;将数据低16位放bx暂存 
        mov     ax,dx 
        mov     dx,0 
        div     cx        ;数据高16位除以除数 
        push    ax        ;商,即为最终结果的高16位 
        mov     ax,bx 
        div     cx        ;高16位余数作为新的高16位、原低16位,除以除数 
                        ;商即为最终结果的低16位 
        mov     cx,dx        ;余数放cx 
        pop     dx        ;高16位 
        pop     bx
        ret 
;不会溢出的除法,注意保护bx。

clrdi:  push        di
        mov        cx,8
n3:     mov        [di],byte ptr 0
        inc        di
        loop        n3
        pop        di
        ret
;将strdn处8个字节清零,以免受到前次结果的影响。

codesg  ends 
        end     start
评论次数(10)  |  浏览次数(39827)  |  类型(汇编作业) |  收藏此文  | 

[  qiangzi   发表于  2010-02-11 17:37  ]

有些代码没看到过

[  sissim   发表于  2010-02-11 22:42  ]

lea是取偏移地址的指令,lea si,strd 功能上相当于 mov si,offset strd。不过说起来,应该是mov和offset的配合使用效率更高。都修改了,谢谢。

[  mcjfo   发表于  2011-06-08 06:40  ]

为什么这条指令会跳过去不执行JMP dd 指令,请高手帮忙???
assume cs:code
data segment
db '1975','1976','1977','1978'
dw 16,2390,8000,16000
dw 3,28,38,130
data ends
stack segment
dw 1,1,1,1,1,1,1,1
stack ends
code segment
start: mov ax,data
       mov ds,ax
       mov ax,0b800h
       mov es,ax
       mov ax,stack
       mov ss,ax
       mov sp,16
       mov si,0
       mov di,4*160+4  //显示年份,从屏幕的第四行第三列开始
       mov cx,4
     b:push cx
       push di
       mov cx,4
     a:mov al,ds:[si]
       mov ah,00000010b
       mov es:[di],ax
       inc si
       add di,2
       loop a
       pop di
       pop cx
       add di,160
       loop b
       mov si,0
       mov bx,0
       mov di,4*160+24    // 被除数显示的位置
       mov cx,4
     e:push bx
       push cx
       mov ax,ds:[si+16]   //从数据段中取出被除数
     d:mov cx,10
       div cx
       mov cx,ax
       add dx,30h
       inc bx
       push ax              //将被除数转化为字符形式,然后显示在年份的后面
       push dx
       mov ax,0b800h
       mov es,ax
       pop dx
       mov al,dl
       mov ah,00000010b
       add bx,bx
       mov es:[di+bx],ax
       pop ax
       jcxz f
       add cx,1
       loop d
     f:add si,2
       add di,160
       pop cx
       pop bx
    loop e
       mov ax,4c00h
       int 21h
code ends
end start

[  游客   发表于  2017-05-19 18:25  ]

注意不溢出的除法。

[  游客   发表于  2017-05-19 18:28  ]

计算人均时,是DD型除以DW型。把DD型的最大值代进去,你的程序,就溢出了。

[  游客   发表于  2017-05-19 18:30  ]

把:DD 5937000,改成:DD 4294967295,你的错误,立刻就暴露出来。呵呵

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码