. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->CALL和RET指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  第10章 课程设计1 实现代码 应该是最简洁的代码了  [待解决] 回复[ 3次 ]   点击[ 636次 ]  
ruder
[帖 主]   [ 发表时间:2013-05-10 09:49 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2011-01-02 12:37
assume cs:code, ds:data, ss:stack

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

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

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

buffer segment
    db 010h dup (0)
buffer ends

stack segment
    db 040h dup (0)
stack ends

code segment
start:
    mov     ax, data                ; 使ds指向data
    mov     ds, ax

    mov     ax, stack               ; 使ss指向stack
    mov     ss, ax
    mov     sp, 040h

    mov     di, 0                   ; di可寻址雇员数

    mov     bh, 4                   ; 设定打印的起始行号
    mov     cx, 21                  ; 设定循环次数
again:
    mov     si, di                  ; 下标di乘以2后存入si
    add     si, si                  ; si可寻址年份和收入

    push    cx                      ; 显示年份
    mov     al, ds:[si].4
    mov     byte ptr ds:[si].4, 0
    mov     dh, bh
    mov     dl, 0
    mov     cl, 00001100B
    call    show_string
    mov     ds:[si].4, al
    pop     cx

    mov     ax, ds:054h[si].0       ; 显示收入
    mov     dx, ds:054h[si].2
    mov     bl, 12
    call    show_dword

    mov     bp, ds:0a8h[di]         ; 雇员数保存在bp里

    div     bp                      ; 显示平均工资
    mov     dx, 0
    mov     bl, 36
    call    show_dword

    mov     ax, bp                  ; 显示雇员数
    mov     bl, 24
    call    show_dword

    inc     bh                      ; 继续处理下一组数据
    add     di, 02h
    loop    again

    mov     ax, 04c00h              ; 程序退出
    int     021h

;--------------------------------------------------------
;  功能 - 以字符串形式显示dword型数据
;  参数 - (dx) = dword的高16位
;         (ax) = dword的低16位
;         (bh) = 行号(取值范围0-24)
;         (bl) = 列号(取值范围0-79)
;  返回 - 无
;--------------------------------------------------------

show_dword:
    push    ds
    push    cx
    push    dx
    push    si
    mov     cx, buffer
    mov     ds, cx
    mov     si, 0
    call    dword_to_string         ; dword转换后存入buffer
    mov     dx, bx
    mov     cl, 00001100B
    call    show_string             ; 显示转换后的字符串
    pop     si
    pop     dx
    pop     cx
    pop     ds
    ret

;--------------------------------------------------------
;  功能 - 将dword转换成十进制的字符串 字符串以0结尾
;  参数 - (dx) = dword的高16位
;         (ax) = dword的低16位
;         (ds:si) = 接收字符串的缓冲
;  返回 - 无
;--------------------------------------------------------

dword_to_string:
    push    ax
    push    cx
    push    dx
    push    si

    mov     cx, 0                   ; 在栈里设置一个循环出栈时的结束标志
    push    cx                      ; 当遇见这个标志时正好结束循环出栈
                                    ; 而这个标志正好做了字符串的结束符
dword_to_string_push:
    mov     cx, 0ah                 ; dword循环除以10
    call    safe_div
    add     cl, '0'                 ; 余数直接转换为ASCII码的十进制
    push    cx                      ; 保存进堆栈
    mov     cx, dx                  ; 如果商是0则转换完毕
    or      cx, ax
    jcxz    dword_to_string_pop
    jmp     dword_to_string_push

dword_to_string_pop:                ; 字符循环出栈 遇到0结束
    pop     cx
    mov     ds:[si], cl
    jcxz    dword_to_string_done
    inc     si
    jmp     dword_to_string_pop

dword_to_string_done:
    pop     si
    pop     dx
    pop     cx
    pop     ax
    ret

;--------------------------------------------------------
;  功能 - 进行不会产生溢出的除法运算
;  参数 - (dx) = dword型数据的高16位
;         (ax) = dword型数据的低16位
;         (cx) = 除数
;  返回 - (dx) = 结果的高16位
;         (ax) = 结果的低16位
;         (cx) = 余数
;--------------------------------------------------------

safe_div:
    push    bx
    push    ax
    mov     ax, dx
    mov     dx, 0
    div     cx
    mov     bx, ax
    pop     ax
    div     cx
    mov     cx, dx
    mov     dx, bx
    pop     bx
    ret

;--------------------------------------------------------
;  功能 - 在指定的位置 用指定的颜色 显示一个用0结束的字符串
;  参数 - (dh) = 行号(取值范围0-24)
;         (dl) = 列号(取值范围0-79)
;         (cl) = 颜色
;         (ds:si) = 字符串首地址
;  返回 - 无
;--------------------------------------------------------

show_string:
    push    es
    push    ax
    push    cx
    push    si
    push    di
    mov     ax, 0b800h              ; 使es指向视频段
    mov     es, ax

    mov     al, 0a0h                ; 计算向视频段的写入地址di
    mul     dh                      ; di = (dh * 80 + dl) * 2
    mov     di, ax
    mov     al, 2
    mul     dl
    add     di, ax

    mov     ah, cl
    mov     ch, 0
show_string_copy:
    mov     cl, ds:[si]
    jcxz    show_string_done
    mov     al, cl
    mov     es:[di], ax
    inc     si
    add     di, 2
    jmp     show_string_copy
show_string_done:
    pop     di
    pop     si
    pop     cx
    pop     ax
    pop     es
    ret
code ends

end start
lonelyhover
[第1楼]   [ 回复时间:2013-05-23 13:44 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-07-18 20:29
平均工资那里应该考虑避免溢出
lonelyhover
[第2楼]   [ 回复时间:2013-05-23 13:49 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-07-18 20:29
显示年份的时候在原数据上操作,虽然采取了保护措施,但仍不赞成,当然,因为保护措施的存在,这不是个错误,而是一种很好的节省空间时间的方法。
hky987654321
[第3楼]   [ 回复时间:2013-08-25 16:46 ]   [引用]   [回复]   [ top ] 
荣誉值:26
信誉值:0
注册日期:2013-07-15 09:25
不是最简洁,还可更简洁。
1、结构上,数据段buffer和栈段stack,均无须定义和设置。数据不转存buffer,直接入栈出栈,感觉更简洁。
子程序show_string的代码显得太长,可考虑,做那么多数据保护是否必要。
2、代码数量上,超过110条了。程序中si与di的关系很简洁,借助它,80多条代码就可实现设计1的要求。
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved