彙編語言-第三版-王爽-課程設計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

 

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