汇编语言-第三版-王爽-课程设计1

课程设计1(p211)、


* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

课程设计1(p211)

# 执行结果

# code

; DATE: 20190614
; DESCRIPTION: 在屏幕上按格式显示数据

assume cs:code

data segment    
    db 16 dup (0)   ; 用于临时保存数据转字符串的结果
    ; 年份
    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, 97497, 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

code segment
start:
    mov ax, data
    mov ds, ax
    mov si, 0       ; ds:si 指向data段中的自定义字符串空间
    call company
    
    mov ax, 4c00H
    int 21H

; 数据处理并显示    
company:
    push ax 
    push bx 
    push cx
    push dx 
    push si
    push di         ; 保护现场

    mov bx, 16      ; ds:bx 指向年份
    mov di, 16
    add di, 168     ; ds:di 指向雇员
    mov dh, 2       ; 屏幕上显示行
    mov cx, 21      ; 一共要显示21行数据
year:
    push cx         ; 颜色cl将覆盖cx
    mov dl, 10      ; 屏幕上显示列
    mov cl, 2       ; 颜色

    ; 年份
    mov ax, [bx]
    mov [si], ax
    mov ax, [bx+2]
    mov [si+2], ax  ; 直接将4Bytes年份复制到ds:si
    mov ax, 0
    mov [si+4], ax  ; 字符串以0结尾
    call show_str
    
    ; 收入
    push dx         ; div中dx为被除数高16位
    mov ax, [bx+84] ; ax存放被除数低16位
    mov dx, [bx+86] ; dx存放被除数高16位
    call ddtoc
    pop dx
    add dl, 10      ; 屏幕上显示列右移10列
    call show_str
    
    ; 雇员
    mov ax, [di]    ; ax存放16位的被除数
    call dtoc
    add dl, 15      ; 屏幕上显示列右移15列
    call show_str

    ; 人均收入
    push dx             ; div指令用dx存储余数
    mov ax, [bx+84]     ; ax存放被除数低16位
    mov dx, [bx+86]     ; dx存放被除数高16位
    div word ptr [di]
    pop dx
    call dtoc           ; 结果的商存放在ax中
    add dl, 10          ; 屏幕上显示列右移10列
    call show_str
    
    pop cx
    inc dh              ; 屏幕上显示行下移一行
    add bx, 4           ; 下一个年份和收入数据
    add di, 2           ; 下一个雇员数据
    loop year
    
    pop di
    pop si
    pop dx
    pop cx
    pop bx
    pop ax      ; 恢复现场
    ret         ; 返回
    
    
; 名称:dtoc
; 功能:将word型数据转变为表示十进制数的字符串,以0结尾
; 参数:(ax)=word型数据,ds:si指向字符串的首地址
; 返回:无
dtoc:
    push ax
    push bx
    push cx
    push dx 
    push si
    
    mov bx, 10    
division:
    mov dx, 0       ; 被除数的高16位
    div bx
    add dx, 30H     ; dx为余数,转为字符
    push dx         ; 余数入栈
    inc si          ; 通过si统计长度
    mov cx, ax      ; ax为商
    jcxz save0
    jmp short division
save0:
    mov cx, si
    mov si, 0
s2:
    pop [si]        ; 余数出栈,保存到ds:si
    inc si          ; 取巧,出栈2Bytes,但si+1;末尾以0结尾
    loop s2
    
    pop si
    pop dx
    pop cx
    pop bx
    pop ax
    ret

    
; 名称:ddtoc
; 功能:将dword型数据转变为表示十进制数的字符串,以0结尾
; 参数:(ax)=dword低16位,(dx)=dowrd高16位,ds:si指向字符串的首地址
; 返回:无
ddtoc:
    push ax
    push cx
    push dx
    push si
    push di

    mov di, 0
change:
    mov cx, 10          ; cx为除数
    call divdw
    add cx, 30H         ; cx为余数, 加48转为字符
    push cx             ; 余数入栈
    inc di              ; 通过di统计余数个数
    mov cx, ax
    or cx, dx           ; 判断商是否为0
    jcxz save
    jmp short change
save:    
    mov cx, di
s1:
    pop [si]            ; 余数出栈,保存到ds:si
    inc si              ; 取巧,出栈2Bytes,但si+1;末尾以0结尾
    loop s1
    
    pop di
    pop si
    pop dx
    pop cx
    pop ax
    ret

    
; 名称:divdw
; 功能:不会产生溢出的除法,被除数为dword,除数为word,结果为dword
; 参数:(ax)=dword低16位 (dx)=dword高16位 (cx)=除数
; 返回:(dx)=结果高16位 (ax)=结果低16位 (cx)=余数
divdw:
    push bx     ; ax cx dx为返回值

    push ax     ; 被除数低16位

    ; 被除数的高16位除法
    mov ax, dx
    mov dx, 0
    div cx

    ; 被除数的低16位除法
    mov bx, ax  ; 高16位除法的商暂移到bx
    pop ax
    div cx

    ; 结果返回
    mov cx, dx  ; 低16位除法的余数移到cx
    mov dx, bx  ; 高16位除法的商移到dx
    
    pop bx
    ret
    

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

    mov ax, 0b800H
    mov es, ax      ; 显示缓冲区 b8000 ~ b8ffff
    
    mov al, 160     ; 一行80个字符,加上颜色属性,占160Bytes
    mul dh          ; 乘以行号
    mov di, ax 
    mov al, 2       ; 内容1Byte、属性1Byte
    mul dl          ; 乘以列号
    add di, ax      ; es:di指向屏幕指定位置对应的显示缓冲区
    
    mov ah, cl      ; 高位字节存储颜色属性
s0:
    mov ch, 0
    mov cl, [si]    ; 给定的字符串以0结尾
    jcxz ok
    mov al, cl      ; 低位字节存储字符ASCII码
    mov es:[di], ax
    inc si          ; 下一个字符
    add di, 2       ; 屏幕显示位置右移2Bytes
    jmp short s0
ok:
    pop es
    pop di
    pop si
    pop dx
    pop cx
    pop ax
    ret
    
code ends
end start

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章