汇编_28-课程设计1

1. 官方答案
assume cs:code
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'
      ;以上是表示 21 年的 21 个字符串
           dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514,
345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
      ;以上是表示 21 年公司总收的 21 个 dword 型数据
           dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
           dw 11542,14430,45257,17800
      ;以上是表示 21 年公司雇员人数的 21 个 word 型数据
data ends
agency segment
             db 8 dup(0)
agency ends
code segment
      start:        mov  ax,0b800h
                    mov  es,ax
                    mov  di,0
                    mov  cx,80*24
      x:            mov  byte ptr es:[di],' '        ;将屏幕清空
                    mov  byte ptr es:[di+1],0
                    inc  di
                    inc  di
                    loop x
                    mov  ax,data
                    mov  es,ax
                    mov  di,0
                    mov  bx,0
                    mov  ax,agency
                    mov  ds,ax
                    mov  si,0
                    mov  dh,4
                    mov  cx,21
      x1:           push cx
                    mov  ax,es:[di]
                    mov  ds:[si],ax
                    mov  ax,es:[di+2]
                    mov  ds:[si+2],ax
                    mov  byte ptr ds:[si+4],0        ;显示年份
                    mov  dl,0
                    mov  cl,2
                    call show_str
                    mov  ax,es:[84+di]
                    push dx
                    mov  dx,es:[84+di+2]
                    call dtoc_dword                  ;显示收入
                    pop  dx
                    mov  dl,20
                    mov  cl,2
                    call show_str
                    mov  ax,es:[84+84+bx]
                    call dtoc_word
                    mov  dl,40                       ;显示雇员数
                    mov  cl,2
                    call show_str
                    mov  ax,es:[84+di]
                    push dx
                    mov  dx,es:[84+di+2]
                    div  word ptr es:[84+84+bx]      ;计算人均收入并显示
                    call dtoc_word
                    pop  dx
                    mov  dl,60
                    mov  cl,2
                    call show_str
                    add  di,4
                    add  bx,2
                    add  dh,1
                    pop  cx
                    loop x1
                    mov  ax,4c00h
                    int  21h
      ;名称:show_str
      ;功能:在屏幕的指定位置, 用指定颜色, 显示一个用 0 结尾的字符串
      ;参数:(dh)=行号, (dl)=列号(取值范围 080), (cl)=颜色, ds:si:该字符串的首地址
      ;返回:显示在屏幕上
      show_str:
                    push ax
                    push cx
                    push dx
                    push es
                    push si
                    push di
                    mov  ax,0b800h
                    mov  es,ax
                    mov  al,160
                    mul  dh
                    add  dl,dl
                    mov  dh,0
                    add  ax,dx
                    mov  di,ax
                    mov  ah,cl
      show_str_x:
                    mov  cl,ds:[si]
                    mov  ch,0
                    jcxz show_str_f
                    mov  al,cl
                    mov  es:[di],ax
                    inc  si
                    inc  di
                    inc  di
                    jmp  show_str_x
      show_str_f:
                    pop  di
                    pop  si
                    pop  es
                    pop  dx
                    pop  cx
                    pop  ax
                    ret
      ;名称:dtoc_word
      ;功能:将一个 word 型数转化为字符串
      ;参数:(ax)=word 型的数据, ds:si 指向字符串的首地址
      ;返回:ds:[si]放此字符串,0 结尾
      dtoc_word:
                    push ax
                    push bx
                    push cx
                    push dx
                    push si
                    mov  bx,0
      dtoc_word_x:
                    mov  dx,0
                    mov  cx,10
                    div  cx
                    mov  cx,ax
                    add  dx,'0'
                    push dx
                    inc  bx
                    jcxz dtoc_word_f
                    jmp  dtoc_word_x
      dtoc_word_f:
                    mov  cx,bx
      dtoc_word_x1:
                    pop  ds:[si]
                    inc  si
                    loop dtoc_word_x1
                    pop  si
                    pop  dx
                    pop  cx
                    pop  bx
                    pop  ax
                    ret
      ;名称:dtoc_dword
      ;功能:将一个 double word 型数转化为字符串
      ;参数:(dx)=数的高八位, (ax)=数的低八位
      ;返回:ds:[si]放此字符串,0 结尾
      ;备注:会用到 divdw 函数
      dtoc_dword:
                    push ax
                    push bx
                    push cx
                    push dx
                    push si
                    mov  bx,0
      dtoc_dword_x:
                    mov  cx,10
                    call divdw
                    push cx
                    inc  bx
                    cmp  ax,0
                    jne  dtoc_dword_x
                    cmp  dx,0
                    jne  dtoc_dword_x
                    mov  cx,bx
      dtoc_dword_x1:
                    pop  ds:[si]
                    add  byte ptr ds:[si],'0'
                    inc  si
                    loop dtoc_dword_x1
                    pop  si
                    pop  dx
                    pop  cx
                    pop  bx
                    pop  ax
                    ret
      ;名称:divdw
      ;功能:除法, 被除数 32, 除数 16,32, 余数 16, 不会溢出
      ;参数:(dx)=被除数高 16, (ax)=被除数低 16, (cx)=除数
      ;返回:(dx)=商高 16, (ax)=商低 16, (cx)=余数
      divdw:
                    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
code ends
end start
2. 方法 2
; 将data段中的数据显示到屏幕上

assume cs:codesg,ds:datasg,ss:stacksg

; 数据段
datasg segment
    ; 表示公司21年的21个字符串, 经过数据分析, 偏移地址范围(0~53H)
    db '1975', '1976', '1977', '1978', '1979', '1980', '1981', '1982', '1983'
    db '1984', '1985', '1986', '1987', '1988', '1989', '1990', '1991', '1982'
    db '1993', '1994', '1995'
    ; 表示21年公司总收入的21个dword型数据, 偏移地址范围(54H~0A7H)
    dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514
    dd 345980, 590827, 808530, 1183000, 1843000, 2759000, 3753000, 4649000, 5937000
    ; 表示21年公司雇员人数的21个word型数据, 偏移地址范围(0A8H, 0D1H)
    dw 3, 7, 9, 13, 28, 38, 130, 220, 476, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226
    dw 11542, 14430, 15257, 17800
datasg ends

tablesg segment
    ; 定义的公司情况表格,一共定义21行;偏移地址范围(0~159H)
    db 21 dup ('year summ ne ?? ')
tablesg ends

; 栈段
stacksg segment stack
    db 128 dup(0)
stacksg ends

; 暂存段
tempsg segment
    db 16 dup(0)
tempsg ends

; 代码段
codesg segment

    start:
        mov ax, datasg
        mov ds, ax

        mov ax, stacksg
        mov ss, ax
        mov sp, 128

; =====================================================================================

        ; 填充表格信息
        mov ax, tablesg
        mov es, ax
        call fillTable

; =====================================================================================

        ; 清理屏幕
        mov ax, 0B800H
        mov es, ax
        call clearScreen

; =====================================================================================

        ; 显示信息
        call showYear
        call showIncome
        call showNumber
        call showAverage

; =====================================================================================

        mov ax, 4c00h
        int 21h

; 功能:将data段中的数据按照如下格式写入到table段中, 并计算21年中的人均收入(取整)
fillTable:
        mov si, 0
        mov di, 0
        mov cx, 21
fillTable1:
        ; 填写年份
        mov ax, ds:[si]
        mov es:[di], ax
        mov ax, ds:[si+2]
        mov es:[di+2], ax
        mov byte ptr es:[di+4], 0H

        ; 填写公司总收入
        mov ax, ds:[si+54h]
        mov es:[di+5], ax
        mov ax, ds:[si+56h]
        mov es:[di+7], ax
        mov byte ptr es:[di+9], 0H

        add si, 4
        add di, 16
        loop fillTable1

        mov si, 0
        mov di, 0
        mov cx, 21
fillTable2:
        ; 填写公司雇员人数
        mov ax, ds:[si+0a8h]
        mov es:[di+10], ax
        mov byte ptr es:[di+12], 0H

        ; 计算人均收入
        mov ax, es:[di+5]
        mov dx, es:[di+7]
        div word ptr es:[di+10]
        mov es:[di+13], ax
        mov byte ptr es:[di+15], 0H

        add si, 2
        add di, 16
        loop fillTable2
        ret

; 功能:清理屏幕 es指向显存
clearScreen:
        mov bx, 0
        mov dx, 0700H
        mov cx, 2000
clearScreen1:
        mov es:[bx], dx
        add bx, 2
        loop clearScreen1
        ret

; 功能:显示年份
showYear:
        mov ax, tablesg
        mov ds, ax

        mov cx, 21
        mov dh, 4
        mov dl, 0
        mov si, 0
showYear1:
        call showStr

        inc dh
        add si, 10H
        loop showYear1
        ret

; 功能:显示总收入
showIncome:
        mov ax, tempsg
        mov ds, ax

        mov cx, 21
        mov bx, 5
        mov si, 0
        mov dh, 4
        mov dl, 7
showIncome1:
        mov ax, tablesg
        mov es, ax

        push dx
        mov ax, es:[bx]
        mov dx, es:[bx+2]
        call dtocdw
        pop dx

        call showStr

        inc dh
        add bx, 10H
        loop showIncome1
        ret

; 功能:显示人数
showNumber:
        mov ax, tempsg
        mov ds, ax

        mov cx, 21
        mov bx, 10
        mov si, 0
        mov dh, 4
        mov dl, 16
showNumber1:
        mov ax, tablesg
        mov es, ax

        push dx
        mov ax, es:[bx]
        call dtoc
        pop dx

        call showStr

        inc dh
        add bx, 10H
        loop showNumber1
        ret

; 功能:显示平均收入
showAverage:
        mov ax, tempsg
        mov ds, ax

        mov cx, 21
        mov bx, 13
        mov si, 0
        mov dh, 4
        mov dl, 23
showAverage1:
        mov ax, tablesg
        mov es, ax

        push dx
        mov ax, es:[bx]
        call dtoc
        pop dx

        call showStr

        inc dh
        add bx, 10H
        loop showAverage1
        ret

; 功能:在指定的位置, 显示一个用0结束的字符串
; @param dh存放行号, 取值范围(0~24)
; @param dl存放列号, 取值范围(0~79)
; @param ds:si存放指向字符串的首地址
showStr:
        ; 将显存段地址放入es拓展寄存器中
        mov ax, 0B800H
        mov es, ax

        push si
        push dx
        push cx
        ; 计算出行的偏移地址
        xor ax, ax
        mov al, 160
        mul dh
        push ax         ; 寄存器不够用, 先放入栈中
        ; 计算出列的偏移地址
        xor ax, ax
        mov al, 2
        mul dl
        ; 将行列偏移地址相加, 得到具体位置的偏移地址,放在di中
        pop dx
        add dx, ax
        mov di, dx

        ; 拿取字符串, 放入显存
        mov ah, 10      ; 将字体属性放到ah中
putStr:
        xor cx, cx
        mov cl, ds:[si]
        jcxz endPutStr
        mov al, ds:[si] ; 将字符串的ascll码放到al中, 这样ax就是一个有属性的可显示字符了
        mov es:[di], ax

        inc si          ; 字符串地址+1, 指向下一个字符
        add di, 2       ; 显示具体位置偏移地址+2, 指向下一个可显示字符
        jmp short putStr
endPutStr:
        pop cx
        pop dx
        pop si
        ret

; 功能:进行不会产生溢出的除法运算
; @param ax 存放被除数的低16; @param dx 存放被除数的高16; @param cx 存放除数
; @return ax 商的低16; @return dx 商的高16; @return cx 余数
divdw:
        push bx
        push si        ; 保留使用的寄存器

        mov bx, ax     ; 保存低位

        mov ax, dx
        mov dx, 0H     ; 进行H/N 的运算
        div cx         ; 因为除数为16位的, 使用div, 则设置的被除数为32位

        mov si, ax     ; 用于保存int(H/N), 因为rem(H/N)*65536就相当于高16, dx了, 故得到的余数在dx直接做高位

        mov ax, bx     ; [rem(H/N)*65536+L]
        div cx         ; [rem(H/N)*65536+L]/N, 结果是的ax保存为16位的低位

        mov cx, dx     ; 将余数写入cx
        mov dx, si     ; 将高位写入dx

        pop si
        pop bx         ; 还原寄存器的值
        ret

; 功能:将word型数据转变为表示十进制的字符串, 字符串以0结尾
; @param ax 要转换的word型数据
; @param ds:si 存放字符串存储的首地址
dtoc:
        push cx
        push bx

        ; 将十六进制数值转化为十进制ascll码
        mov di, si
        xor bx, bx
        push bx         ; 设置字符串的结束标志
        mov bx, 10
dtoc1:
        xor dx, dx
        div bx          ; ÷10
        mov cx, ax      ; 将商给cx
        add dx, 30H     ; 0~9数字的ascll码 = 自己 + 30H
        push dx         ; 将转换好的ascll码入栈
        jcxz dtoc2
        jmp dtoc1
dtoc2:
        pop cx          ; 获取入栈的字符串
        jcxz dtoc3
        ; 到了这里, 栈里已经存放了转换好的字符串, 我们拿出来放到ds:si的备份ds:di中即可
        mov byte ptr ds:[di], cl
        inc di
        jmp dtoc2
dtoc3:
        mov byte ptr ds:[di], 0
        pop bx
        pop cx
        ret

; 功能:将dword型数据转变为表示十进制的字符串, 字符串以0结尾
; @param ax 要转换的dword型数据低16位 dx 要转换的dword型数据高16; @param ds:si 存放字符串存储的首地址
dtocdw:
        push cx

        ; 将十六进制数值转化为十进制ascll码
        mov di, si
        xor cx, cx
        push cx         ; 设置字符串的结束标志
dtocdw2:
        mov cx, 10
        call divdw      ; ÷10
        add cx, 30H     ; 0~9数字的ascll码 = 自己 + 30H
        push cx         ; 将转换好的ascll码入栈
        xor cx, cx
        add cx, ax
        add cx, dx
        jcxz dtocdw1
        jmp dtocdw2
dtocdw1:
        pop cx          ; 获取入栈的字符串
        jcxz dtocdw3
        ; 到了这里, 栈里已经存放了转换好的字符串, 我们拿出来放到ds:si的备份ds:di中即可
        mov byte ptr ds:[di], cl
        inc di
        jmp dtocdw1
dtocdw3:
        mov byte ptr ds:[di], 0
        pop cx
        ret

codesg ends

end start
3. 课件版
assume cs:code,ds:data,ss:stack

data segment
     ; 表示21年的21个字符串 年份的数据占了21*4=84=54H
     ; 1975 = 31 39 37 35 = 4byte = FF = 2^8 = 0-255
          db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
          db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
          db '1993','1994','1995'

     ; 表示21年公司总收入的21个dd型数据 收入的数据占了21*4=84=54H 4字节 32bit
     ; 16 = 10 00 00 00 = 4byte = 2^32 = 0-4,294,967,295
          dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
          dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000

     ; 表示21年公司雇员人数的21个word型数据 雇员的数据占了21*2=42=2AH 2字节 16bit
     ; 3 = 03 00 = 2byte = 2^16 = 0-65535
          dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
          dw 11542,14430,15257,17800

     ; 年份是0H~53H, 收入是54H~A7H, 雇员是A8H~D1H
     ; data段地址+84(年份所占字节)=收入的数据起始地址
     ; data段地址+168(年份所占字节84+收入所占字节)=雇员的数据起始地址


     ; -d ds:0
     ; 0E24:0000  31 39 37 35 31 39 37 36-31 39 37 37 31 39 37 38   197519761977197
     ; 0E24:0010  31 39 37 39 31 39 38 30-31 39 38 31 31 39 38 32   197919801981198
     ; 0E24:0020  31 39 38 33 31 39 38 34-31 39 38 35 31 39 38 36   198319841985198
     ; 0E24:0030  31 39 38 37 31 39 38 38-31 39 38 39 31 39 39 30   198719881989199
     ; 0E24:0040  31 39 39 31 31 39 39 32-31 39 39 33 31 39 39 34   199119921993199
     ; 0E24:0050  31 39 39 35 10 00 00 00-16 00 00 00 7E 01 00 00   1995........~..
     ; 0E24:0060  4C 05 00 00 56 09 00 00-40 1F 00 00 80 3E 00 00   L...V...@....>.
     ; 0E24:0070  A6 5F 00 00 91 C3 00 00-C7 7C 01 00 81 24 02 00   ._.......|...$.
     ; 0E24:0080  8A 03 03 00 7C 47 05 00-EB 03 09 00 CA 42 0C 00   ....|G.......B.
     ; 0E24:0090  18 0D 12 00 38 1F 1C 00-58 19 2A 00 28 44 39 00   ....8...X.*.(D9
     ; 0E24:00A0  28 F0 46 00 68 97 5A 00-03 00 07 00 09 00 0D 00   (.F.h.Z........
     ; 0E24:00B0  1C 00 26 00 82 00 DC 00-DC 01 0A 03 E9 03 A2 05   ..&............
     ; 0E24:00C0  D2 08 E9 0A C5 0F 03 16-22 20 16 2D 5E 38 99 3B   ........" .-^8.
     ; 0E24:00D0  88 45 00 00 00 00 00 00-00 00 00 00 00 00 00 00   .E.............
     ; 0E24:00E0  79 65 61 72 20 73 75 6D-6D 20 6E 65 20 3F 3F 20   year summ ne ??
     ; 0E24:00F0  79 65 61 72 20 73 75 6D-6D 20 6E 65 20 3F 3F 20   year summ ne ??
data ends


table segment
     ;                 0123456789ABCDEF
           db 21 dup ('year summ ne ?? ')
table ends

stack segment stack
           db 128 dup (0)
stack ends

string segment
            db 10 dup ('0'),0,0,0
string ends

code segment

     start:               mov  ax,stack
                          mov  ss,ax
                          mov  sp,128

                          call input_table
                          call clear_screen
                          call output_table

                          mov  ax,4C00H
                          int  21H
     ;=========================================================
     clear_screen:
                          mov  bx,0B800H
                          mov  es,bx

                          mov  bx,0
                          mov  dx,0700H
                          mov  cx,2000

     clearScreen:         mov  es:[bx],dx
                          add  bx,2
                          loop clearScreen

                          ret
     ;=========================================================
     output_table:        call init_reg_outputTable

                          mov  cx,21
                          mov  si,0                     ;ds:[si]
                          mov  di,160*3
                          mov  bx,9                     ;string[9]

     outputTable:         call show_year
                          call show_sum
                          call show_employee
                          call show_average
                          add  di,160
                          add  si,16
                          loop outputTable

                          ret
     ;=========================================================
     show_average:        push ax
                          push bx
                          push cx
                          push dx
                          push ds
                          push es
                          push si
                          push di

                          mov  ax,ds:[si+13]
                          mov  dx,0

                          call isShortDiv
                          call init_reg_showString
                          add  di,40*2
     ;                       0123456789ABCDEF
     ;		db	21 dup ('year summ ne ?? ')
                          call show_string

                          pop  di
                          pop  si
                          pop  es
                          pop  ds
                          pop  dx
                          pop  cx
                          pop  bx
                          pop  ax
                          ret
     ;=========================================================
     show_employee:       push ax
                          push bx
                          push cx
                          push dx
                          push ds
                          push es
                          push si
                          push di

                          mov  ax,ds:[si+10]
                          mov  dx,0

                          call isShortDiv
                          call init_reg_showString
                          add  di,23*2
     ;                       0123456789ABCDEF
     ;		db	21 dup ('year summ ne ?? ')
                          call show_string

                          pop  di
                          pop  si
                          pop  es
                          pop  ds
                          pop  dx
                          pop  cx
                          pop  bx
                          pop  ax
                          ret
     ;=========================================================
     show_sum:            push ax
                          push bx
                          push cx
                          push dx
                          push ds
                          push es
                          push si
                          push di

                          mov  ax,ds:[si+5]
                          mov  dx,ds:[si+7]

                          call isShortDiv
                          call init_reg_showString
                          add  di,10*2
     ;                       0123456789ABCDEF
     ;		db	21 dup ('year summ ne ?? ')
                          call show_string

                          pop  di
                          pop  si
                          pop  es
                          pop  ds
                          pop  dx
                          pop  cx
                          pop  bx
                          pop  ax
                          ret
     ;=========================================================
     show_string:         push cx
                          push ds
                          push es
                          push si
                          push di

     showString:          mov  cx,0
                          mov  cl,ds:[si]
                          jcxz showStringRet
                          mov  es:[di],cl
                          add  di,2
                          inc  si
                          jmp  showString

     showStringRet:       pop  di
                          pop  si
                          pop  es
                          pop  ds
                          pop  cx
                          ret
     ;=========================================================
     init_reg_showString:
                          mov  si,bx

                          mov  bx,string
                          mov  ds,bx

                          mov  bx,0B800H
                          mov  es,bx

                          ret
     ;=========================================================
     isShortDiv:          mov  cx,dx
                          jcxz shortDiv
                          push ax
                          mov  bp,sp
                          mov  cx,10
                          call long_div                 ;	ip	ax
                          add  sp,2
                          add  cl,30H
                          mov  es:[bx],cl
                          dec  bx
                          jmp  isShortDiv

     shortDivRet:         ret

     ;=========================================================
     long_div:
                          mov  ax,dx
                          mov  dx,0
                          div  cx
                          push ax
                          mov  ax,ss:[bp+0]
                          div  cx
                          mov  cx,dx
                          pop  dx

                          ret
     ;=========================================================
     shortDiv:            mov  cx,10
                          div  cx
                          add  dx,30H
                          mov  es:[bx],dl
                          mov  cx,ax
                          jcxz shortDivRet
                          dec  bx
                          mov  dx,0
                          jmp  shortDiv
     ;=========================================================
     show_year:           push bx
                          push cx
                          push ds
                          push es
                          push si
                          push di

                          mov  bx,0B800H
                          mov  es,bx

                          mov  cx,4
                          add  di,3*2

     showYear:            mov  dl,ds:[si]
                          mov  es:[di],dl
                          inc  si
                          add  di,2
                          loop showYear

                          pop  di
                          pop  si
                          pop  es
                          pop  ds
                          pop  cx
                          pop  bx
                          ret
     ;=========================================================
     init_reg_outputTable:
                          mov  bx,table
                          mov  ds,bx

                          mov  bx,string
                          mov  es,bx

                          ret
     ;=========================================================
     input_table:         call init_reg_intputTable

                          mov  si,0
                          mov  di,21*4*2                ;ds:[si]	ds:[di]		es:[bx]
                          mov  bx,0
                          mov  cx,21

     inputTable:          push ds:[si+0]
                          pop  es:[bx+0]
                          push ds:[si+2]
                          pop  es:[bx+2]

                          mov  ax,ds:[si+21*4]
                          mov  dx,ds:[si+21*4+2]
                          mov  es:[bx+5],ax
                          mov  es:[bx+7],dx

                          push ds:[di+0]
                          pop  es:[bx+10]

                          div  word ptr es:[bx+10]

                          mov  es:[bx+13],ax

     ;                       0123456789ABCDEF
     ;		db	21 dup ('year summ ne ?? ')

                          add  si,4
                          add  di,2
                          add  bx,16
                          loop inputTable
                          ret
     ;=========================================================
     init_reg_intputTable:
                          mov  bx,data
                          mov  ds,bx

                          mov  bx,table
                          mov  es,bx

                          ret

code ends
end start

你可能感兴趣的:(04_汇编_01,汇编)