汇编语言期末复习——第五章 模块化程序设计

Posted hotaru蛍

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编语言期末复习——第五章 模块化程序设计相关的知识,希望对你有一定的参考价值。

一、子程序结构

  • 子程序=函数=过程
  • 子程序指令
    • 子程序调用指令
      • CALL LABEL ;调用标号、子程序名指定的子程序
      • 分成近调用(段内调用)和远调用(段间调用)
      • 入栈返回地址:将CALL下条指令的地址压入堆栈
        • 近调用:IP入栈
        • 远调用:CS和IP都入栈
    • 子程序返回指令
      • RET
      • 分为有参数返回和无参数返回,都是出栈返回地址
    • 过程定义伪指令
      • 过程名  PROC
        …………
        …………
        过程名  ENDP

        过程定义应该书写于.EXIT和END之间;也可以安排在主程序开始执行的第一条语句之前

      • PROC后面可以加参数:NEAR/FAR
  • 子程序设计
    • 利用过程定义伪指令声明
    • 最后利用RET返回主程序,主程序执行CALL指令调用子程序
    • 压入弹出成对使用使堆栈保持平衡
    • 子程序开始时保护用到的寄存器内容,返回前逆序弹出恢复到原来的寄存器中。
    • 安排在代码段的主程序之外
    • 允许嵌套和递归
  •   例:回车换行子程序
    • ;eg502.asm
          .model small
          .stack
          .data
      
          .code
          .startup
          
          call dispcrlf
      
          .exit
      dispcrlf    proc    ;回车换行子程序
          push ax    ;保护寄存器
          push dx
          mov dl,0dh    ;输出回车字符
          mov ah,2
          int 21h
          mov dl,0ah    ;输出换行字符
          mov ah,2
          int 21h
          pop dx    ;恢复寄存器
          pop ax
          ret    ;子程序返回
      dispcrlf    endp
      
          end

二、参数传递

  • 传递参数的多少反应程序模块间的耦合程度
  • 传递的内容:
    • 数据本身
    • 数据的存储地址
  • 传递方法:
    • 寄存器
    • 变量
    • 堆栈
  1. 寄存器传递参数
    • 把参数存于约定的寄存器
      • 少量数据直接传递数值
      • 大量数据只能传递地址
    • 带有出口参数的寄存器不能保存和恢复
    • 使用低八位寄存器时不保证不影响高八位数据
    • 例:显示一个数据的数值(数值和ASC码的转换)
      • ;eg410.asm
            .model small
            .stack
            .data
        STRING DB \'AX=\',4 DUP(?),\'H\',\'$\'
            .CODE
            .startup
                MOV AX,123AH
                MOV CX,4
                XOR BX,BX
            AGAIN:
                ROL AX,1
                ROL AX,1
                ROL AX,1
                ROL AX,1
                PUSH AX
                CALL HTOASC
                MOV STRING+3[BX],AL
                INC BX
                POP AX
                LOOP AGAIN
        
                MOV AH,9
                MOV DX,OFFSET STRING
                INT 21H
            .exit
                HTOASC PROC
                AND AL,0FH
                OR AL,30H
                CMP AL,\'9\'
                JBE ABCD
                ADD AL,7
                ABCD: RET
                HTOASC ENDP
        
            end

         

    • 有符号十进制整数的显示
      • ;eg504.asm
            .model small
            .stack
            .data
        array    dw 6789,-1234,0,1,-9876,32767,-32768,5678,-5678,9000
        count    = lengthof array
            .code
            .startup
            mov cx,count
            xor bx,bx
        again:    mov ax,array[bx]     ;将AX=入口参数
            call dispsiw    ;调用子程序,显示一个数据
            add bx,type array
            call dispcrlf    ;光标回车换行以便显示下一个数据
            loop again
            .exit
        dispsiw    proc    ;显示有符号十进制数的通用子程序
            push ax    ;入口参数:AX=欲显示的数据(补码)
            push bx
            push dx
            test ax,ax    ;判断数据是零、正数或负数
            jnz dsiw1
            mov dl,\'0\'    ;是零,显示“0”后退出
            mov ah,2
            int 21h
            jmp dsiw5
        dsiw1:    jns dsiw2    ;是负数,显示“-”
            mov bx,ax    ;AX数据暂存于BX
            mov dl,\'-\'
            mov ah,2
            int 21h
            mov ax,bx
            neg ax    ;数据求补(绝对值)
        dsiw2:    mov bx,10
            push bx    ;10压入堆栈,作为退出标志
        dsiw3:    cmp ax,0    ;数据(商)为零,转向显示
            jz dsiw4
            xor dx,dx    ;扩展被除数DX.AX
            div bx    ;数据除以10:DX.AX÷10
            add dl,30h    ;余数(0~9)转换为ASCII码
            push dx    ;数据各位先低位后高位压入堆栈
            jmp dsiw3
        dsiw4:    pop dx    ;数据各位先高位后低位弹出堆栈
            cmp dl,10    ;是结束标志10,则退出
            je dsiw5
            mov ah,2    ;进行显示
            int 21h
            jmp dsiw4
        dsiw5:    pop dx
            pop bx
            pop ax
            ret    ;子程序返回
        dispsiw    endp
        
        dispcrlf    proc    ;回车换行子程序
            push ax    ;保护寄存器
            push dx
            mov dl,0dh    ;输出回车字符
            mov ah,2
            int 21h
            mov dl,0ah    ;输出换行字符
            mov ah,2
            int 21h
            pop dx    ;恢复寄存器
            pop ax
            ret    ;子程序返回
        dispcrlf    endp
        
            end

         

  2. 变量传递参数
    • 子程序和主程序如果在同一模块不需要特殊说明
    • 如果不在同一个模块需要利用PUBLEC EXTREN说明
    • 例:
      • 二进制输入程序
        ;eg505.asm
            .model small
            .stack
            .data
        count    = 5
        array    dw count dup(0)
        temp    dw ?    ;共享变量
            .code
            .startup
            mov cx,count
            mov bx,offset array
        again:    call readbw    ;调用子程序,输入一个数据
            mov ax,temp    ;获得出口参数
            mov [bx],ax    ;存放到数据缓冲区
            add bx,type array
            call dispcrlf    ;光标回车换行以便输入下一个数据
            loop again
            .exit
        
        readbw    proc    ;二进制输入子程序
            push ax    ;出口参数:共享变量TEMP
            push bx
             push cx
        rdbw1:    xor bx,bx    ;BX用于存放二进制结果
            mov cx,16    ;限制输入字符的个数
        rdbw2:    mov ah,1    ;输入一个字符
            int 21h
            cmp al,\'0\'    ;检测键入字符是否合法
            jb rderr    ;不合法则返回重新输入
            cmp al,\'1\'
            ja rderr
            sub al,\'0\'    ;对输入的字符进行转化
            shl bx,1    ;BX的值乘以2
            or bl,al    ;BL和AL相加
            loop rdbw2    ;循环键入字符
            mov temp,bx    ;把BX的二进制结果存放TEMP返回
            pop cx
            pop bx
            pop ax
            ret
        rderr:     push ds    ;保护DS
            mov ax,cs    ;因信息保存在代码段,所以需要设置DS=CS
            mov ds,ax
            lea dx,errmsg    ;显示错误信息
            mov ah,9
            int 21h
            pop ds    ;恢复DS
            jmp rdbw1
        errmsg    db 0dh,0ah,\'Input error, enter again: $\'
        readbw    endp
        
        dispcrlf    proc    ;回车换行子程序
            push ax    ;保护寄存器
            push dx
            mov dl,0dh    ;输出回车字符
            mov ah,2
            int 21h
            mov dl,0ah    ;输出换行字符
            mov ah,2
            int 21h
            pop dx    ;恢复寄存器
            pop ax
            ret    ;子程序返回
        dispcrlf    endp
        
            end

         

      • 有符号十进制数输入程序
        ;eg506.asm
            .model small
            .stack
            .data
        count    = 5
        array    dw count dup(0)
        temp    dw ?    ;共享变量
            .code
            .startup
            mov cx,count
            mov bx,offset array
        again:    call readsiw    ;调用子程序,输入一个数据
            mov ax,temp    ;获得出口参数
            mov [bx],ax    ;保存到数据缓冲区
            add bx,2
            call dispcrlf    ;分行
            loop again
            .exit
        readsiw    proc    ;输入有符号十进制数的通用子程序
            push ax    ;出口参数:变量TEMP=补码表示的二进制数值
            push bx    ;说明:负数用“-”引导
            push cx
            xor bx,bx    ;BX保存结果
            xor cx,cx    ;CX为正负标志,0为正,-1为负
        rsiw0:    mov ah,1    ;输入一个字符
            int 21h
            cmp al,\'+\'    ;是“+”,继续输入字符
            jz rsiw1
            cmp al,\'-\'    ;是“-”,设置-1标志
            jnz rsiw2
            mov cx,-1
        rsiw1:    mov ah,1    ;继续输入字符
            int 21h
        rsiw2:    cmp al,\'0\'    ;不是0~9之间的字符,则输入数据结束
            jb rsiw3
            cmp al,\'9\'
            ja rsiw3
            sub al,30h    ;是0~9之间的字符,则转换为二进制数
            xor ah,ah    ;AL零位扩展为AX
            shl bx,1    ;利用移位和加法实现数值乘10:BX←BX×10
            mov dx,bx    ;参见例3-8
            shl bx,1
            shl bx,1
            add bx,1
            add bx,ax    ;已输入数值乘10后,与新输入数值相加
            jmp rsiw1    ;继续输入字符
        rsiw3:    cmp cx,0    ;是负数,进行求补
            jz rsiw4
            neg bx
        rsiw4:    mov temp,bx    ;设置出口参数
            pop cx
            pop bx
            pop ax
            ret    ;子程序返回
        readsiw    endp
        
        dispcrlf    proc    ;回车换行子程序
            push ax    ;保护寄存器
            push dx
            mov dl,0dh    ;输出回车字符
            mov ah,2
            int 21h
            mov dl,0ah    ;输出换行字符
            mov ah,2
            int 21h
            pop dx    ;恢复寄存器
            pop ax
            ret    ;子程序返回
        dispcrlf    endp
        
            end

         

  3. 堆栈传递参数
    1. 注意PUSH后不能是常数
    2. 例子:
      • 计算有符号数的平均值程序
        ;eg507.asm
            .model small
            .stack
            .data
        array    dw 675, 354, -34, 198, 267, 0, 9, 2371, -67, 4257
            .code
            .startup
            mov ax,lengthof array
            push ax    ;压入数据个数
            mov bx,offset array
            push bx    ;压入数组的偏移地址
            call mean    ;调用求平均值子程序,出口参数:AX=平均值(整数部分)
            add sp,4    ;平衡堆栈(压入了4个字节数据)
            call dispsiw    ;显示
        
            .exit
        mean    proc    ;计算16位有符号数平均值子程序
            push bp    ;入口参数:顺序压入数据个数和数组偏移地址
            mov bp,sp    ;出口参数:AX=平均值
            push bx    ;保护寄存器
            push cx
            push dx
            mov bx,[bp+4]    ;BX=堆栈中取出的偏移地址
            mov cx,[bp+6]    ;CX=堆栈中取出的数据个数
            xor ax,ax    ;AX保存和值
        mean1:    add ax,[bx]    ;求和
            add bx,type array    ;指向下一个数据
            loop mean1    ;循环
            cwd    ;将累加和AX符号扩展到DX
            idiv word ptr [bp+6]    ;有符号数除法,AX=平均值(余数在DX中)
            pop dx    ;恢复寄存器
            pop cx
            pop bx
            pop bp
            ret
        mean    endp
        dispsiw    proc    ;显示有符号十进制数的通用子程序
            push ax    ;入口参数:AX=欲显示的数据(补码)
            push bx
            push dx
            test ax,ax    ;判断数据是零、正数或负数
            jnz dsiw1
            mov dl,\'0\'    ;是零,显示“0”后退出
            mov ah,2
            int 21h
            jmp dsiw5
        dsiw1:    jns dsiw2    ;是负数,显示“-”
            mov bx,ax    ;AX数据暂存于BX
            mov dl,\'-\'
            mov ah,2
            int 21h
            mov ax,bx
            neg ax    ;数据求补(绝对值)
        dsiw2:    mov bx,10
            push bx    ;10压入堆栈,作为退出标志
        dsiw3:    cmp ax,0    ;数据(商)为零,转向显示
            jz dsiw4
            xor dx,dx    ;扩展被除数DX.AX
            div bx    ;数据除以10:DX.AX÷10
            add dl,30h    ;余数(0~9)转换为ASCII码
            push dx    ;数据各位先低位后高位压入堆栈
            jmp dsiw3
        dsiw4:    pop dx    ;数据各位先高位后低位弹出堆栈
            cmp dl,10    ;是结束标志10,则退出
            je dsiw5
            mov ah,2    ;进行显示
            int 21h
            jmp dsiw4
        dsiw5:    pop dx
            pop bx
            pop ax
            ret    ;子程序返回
        dispsiw    endp
            end

         

三、宏结构

  1. 宏汇编
    1. 定义和调用
      • ;声明
        宏名 MACRO[形参表] …… …… ENDM
        ;调用
        宏名 实参列表
      • 例:
        • 宏定义
          WriteString    macro msg
                  push ax
                  push dx
                  lea dx,msg
                  mov ah,9
                  int 21h
                  pop dx
                  pop ax
                  endm
        • 宏调用
          WriteString  msg
        • 宏展开
          push ax
              push dx
              lea dx,msg
              mov ah,9
              int 21h
              pop dx
              pop ax
    2. 宏和子程序
      • 宏:
        • 仅是源程序级的简化:宏调用在汇编时进行程序语句的展开,不需要返回;不减小目标程序,执行速度没有改变
        • 通过形参、实参结合实现参数传递,简捷直观、灵活多变

        • 当程序段较短或要求较快执行时,应选用宏

      • 子程序

        • 还是目标程序级的简化:子程序调用在执行时由CALL指令转向、RET指令返回;形成的目标代码较短,执行速度减慢

        • 需要利用寄存器、存储单元或堆栈等传递参数

        • 当程序段较长或为减小目标代码时,要选用子程序

  2. 一些其他的说明

    • MASM具体支持的多模块程序结构的方法:

      • 源文件包含

      • 模块连接

      • 子程序库

      • 库文件包含

    •  源文件包含

      • 各种常量定义、声明语句等组织在包含文件(*.inc)

      • 常用的或有价值的宏定义放在宏定义文件(*.mac)

      • 常用的子程序形成汇编语言源文件(*.asm)

    • 使用源文件包含伪指令INCLUDE将指定的文本文件内容插入主题源程序文件。  

四、课后习题!

5.1(1)指令“CALL BX“采用了指令的什么寻址方式?

    寄存器间接寻址

  (5)子程序采用堆栈传递参数,为什么要特别注意堆栈平衡问题?

    子程序保持堆栈平衡才能保证执行RET指令时当前栈顶的内容是正确的返回地址。

    主程序保持平衡才能释放传递参数占用的堆栈空间,否则多次调用可能使堆栈溢出。

5.2 判断题

  (2)CALL指令的执行并不影响堆栈指针SP。

    错,IP入栈 sp-2

  (5)子程序需要保护寄存器,包括保护传递入口参数和出口参数的通用寄存器。

    错,出口参数寄存器不能保护。

  (6)利用INCLUDE包含的源文件实际上只是源程序的一部分。

    对。

  (7)宏调用与子程序调用一样都要使用CALL指令实现。

    错。宏调用:宏名+参数列表

  (8)宏定义可以与子程序一样,书写与主程序之后。

    错,不可以。

5.3 填空题

  (1)指令”RET i16"的功能相当于"RET"指令和“ADD SP,    2    .”组合。

  (4)数值10在计算机内部用二进制“1010”编码表示,用十六进制表达是:    0AF   .如果将该编码加37H,则为   41H   ,他是字符   A   的ASCII码值。

  (5)利用堆栈传递子程序参数的方法是固定的,例如寻址堆栈段数据的寄存器是   BP   

  (7)过程定义开始是“TEST PROC"语句,则过程定义结束的语句是   TEST ENDP  。宏定义开始是”DISP MACRO"语句,则宏定义结束的语句是   ENDM  

5.5 请按如下说明编写子程序。

子程序功能:把用ASCII码表示的两位十进制数转换为压缩BCD码

入口参数:DH=十位数的ASCII码,DL=个位数的ASCII码

出口参数:AL=对应BCD码

    ;把用asc码表示的两位十进制数转换称压缩的BCD码
    ;入口参数:DH=十位数的ASC码,DL=个位数的ASC码
    ;出口参数:AL=对应的BCD码
    .model small
    .stack
    .data    ;数据段
        inmsg    db \'Enter two numbers(0-9):  $\'
        errmsg    db 0dh,0ah,\'Input error, enter again: $\'
    .code    ;代码段,主程序
    .startup
    mov dx,offset inmsg
    mov ah,9
    int 21h
    
    ;输入两位十进制数字,结果分别保存到DH和DL
rdhw1:    xor dx,dx    ;;DX一开始是0哇
    mov bx,2    ;限制输入字符的个数
    mov cl,8
rdhw2:    mov ah,1
    int 21h    ;输入一个字符;;输入进AL
    cmp al,\'0\'    ;检测键入字符是否合法
    jb rderr    ;不合法则返回重新输入
    cmp al,\'9\'
    ja rderr    ;不合法则返回重新输入
    shl dx,cl;;将十位上的数左移至高八位DH上 在第二次循环的时候起作用!!
    or dl,al;;这步应该是相当于ADD DL,AL吧
    dec bx
    jnz rdhw2 ;继续输入    
    call btobcd ;调用子程序
    int 3   ;中断
    jmp done
    
rderr:     
    mov dl,0dh    ;输出回车字符
    mov ah,2
    int 21h
    mov dl,0ah    ;输出换行字符
    mov ah,2
    int 21h
    lea dx,errmsg     ;显示错误信息
    mov ah,9
    int 21h
    jmp rdhw1 ;重新输入
done: nop
    .exit    ;主程序结束,退出
    
btobcd    proc    ;子程序
    ;出口参数:AL=输入的数据
    push cx
    xor ax,ax
   mov cl,4
   and dh,0fh    ;dh高4位清零
    or al,dh    ;AL和DH相加;;AL不是零么???
    and dl,0fh    ;减30H;;为啥不直接用SUB呢???为什么???
    shl ax,cl    ;AX左移4位
    or al,dl    ;AL和DL相加
    pop cx
    ret
btobcd endp
    end

;为什么子程序保护了CX不保护DX?? 入口参数不用保护嘛??

 

5.7 编写一个程序,在键盘上按一个键,将其返回的ASCII码值表示出来,如果按下ESC键(1BH)则退出。

;显示输入字符的ASC码
;如果输入的是ESC(1BH)则退出
    .model small
    .stack
    .data
asc db \'00H\',13,10,\'$\'
crlf db 13,10,\'$\'
    .code
    .startup
ReadAsc:    
   mov ah,1
    int 21h
    cmp al,1Bh
    jz done ;输入一个字符,输入ESC退出;ESC的ASCii码为1BH
    mov dx,offset crlf
    mov ah,9
    int 21h    ;输出回车换行
    mov cx,2
    xor bx,bx;;BX用做asc数组下标
again:    
    rol al,1    ;高4位循环移位进入低4位,作为子程序的入口参数
    rol al,

计算机组成原理期末复习必备知识点大全——第五章(输入输出系统)

前文导读:

计算机组成原理第一章

计算机组成原理第三章

计算机组成原理第四章

一、概述

1)输入输出系统的发展

输入输出系统发展共经历4个阶段:

早期阶段→接口模块和DMA阶段→通道阶段→I/O处理机阶段

1.早期阶段:CPU和外设分散连接、串行工作、耦合性强,机器速度慢、价格高。

 2.接口模块和DMA阶段:具有总线模式,主机通过各种接口连接外设,具有中断或DMA功能。

 3.通道阶段:

通道是用来负责管理I/O设备以及实现主存与I/O设备之间交换信息的部件,可视为从属于CPU的专用处理器。

通道具有专门指令,能独立执行由通道指令编写的输入输出程序。

4.I/O处理机阶段: 外围处理机又称为I/O处理机,独立于主机工作,除了具备通道功能之外,还具备码制转换、格式处理、数据校验等功能。

2)输入输出系统的组成

输入输出系统由I/O软件和I/O硬件组成两部分组成。

3)I/O设备与主机的联系方式

I/O设备编址方式:

统一编址: I/O占用存储器地址空间,无须专门的I/O指令。减少了存储器最大容量。采用不同地址码来区分访问对象。

独立编址: I/O地址与存储器地址分开,采用专门指令来访问I/O。不占用主存容量。采用不同指令形式来区分访问对象。

设备寻址:每台设备都有设备号,启动设备时,由I/O指令的设备码字段直接指出设备号,经接口中的设备选择电路选中设备。

传送方式:

并行:多位同时传送,需要多条数据线,速度快。

串行:一条数据线和一条地线,逐位传送,速度慢,适用于远距离传送。

4)I/O设备与主机信息传送控制方式

程序查询方式:CPUI/O串行工作, I/O工作CPU原地踏步。

中断方式:CPU和I/O部分并行工作,在中断服务子程序中完成数据的传送。

中断程序消除了CPU原地踏步的情况,但是,CPU在响应中断请求后,必须暂停现程序,转而去执行中断服务子程序,消耗了CPU资源,并且,中断处理过程是有开销的。 

DMA方式:在主存和I/O之间建立数据传送的直接通道,由DMA控制器来完成信息传送,不需要中断CPU的运行。进一步提高了CPUI/O的并行程度。

周期窃取:若出现DMA和CPU同时访问主存,CPU总是将总线占有权让给DMA,通常把DMA的这种占有称为窃取或挪用。窃取的时间一般是一个存取周期,所以称为窃取周期。

三种方式比较:

通道方式:

外围处理机方式:

二、I/O设备

三、I/O接口

接口可以看做两个系统或部件之间的交接部分,它既是两种硬件设备之间的连接电路,也可以看做两个软件之间的共同逻辑边界。

 每一台I/O设备都是通过I/O接口挂到系统总线上的。I/O总线包括数据线、设备选择线、命令线和状态线。

I/O接口的基本组成

数据线:数据线是I/O设备与主机之间数据代码的传输线。

设备选择线:设备选择线是用来传送设备码的。

命令线:命令线主要是用以传输CPU向设备发出的各种命令信号。

状态线:状态线是将I/O设备的状态向主机报告的信号线。

程序查询方式

程序查询方式的核心问题在于每时每刻需不断查询I/O设备是否准备就绪。

传送一个数据的流程

 程序中断方式

 中断 计算机在执行程序的过程中,当出现异常情况或特殊请求时,CPU停止现行程序的运行,转向对这些异常情况或特殊请求的处理,处理结束后再返回到现行程序的断点处,继续执行原程序,这就是中断。

中断接口电路:

INTR  中断请求触发器               INTR=1有请求

MASK中断屏蔽触发器               MASK=1被屏蔽

D  完成触发器

 

例题:结合程序中断方式,简要说明I/O设备向CPU提出中断请求的条件

没有中断屏蔽信号mask=0,收到来自CPU中断查询,d触发器为1,设备工作结束 

程序中断方式接口电路的基本组成

CPU响应中断的条件和时间

条件:CPU允许中断:中断允许触发器EINT=1。(开中断、关中断指令可以改变EINT

相关中断的掩码(MASK)为0

 时间:每条指令执行结束(CPU发出中断查询信号(将INTR1))

中断处理的五个阶段:

中断请求:INTR

中断判优:链式排队

中断响应:INTA,得到中断号

中断服务:根据中断号查中断向量表,得到中断入口地址,跳转到中断服务程序

中断返回:从中断服务程序中返回到源程序继续执行

中断服务程序流程

保护现场

        断点保护: 中断隐指令完成

        保存寄存器值:进栈指令

中断服务:(视情形开中断)

恢复现场

       出栈指令

中断返回

        中断返回指令

单重中断与多重中断

单重中断:不允许中断现行的中断服务程序

多重中断(中断嵌套):允许更高级别的中断源中断现行的中断服务程序

DMA方式

DMA访问主存有三种可能:

CPU此时不访存:总线立刻交给DMA

CPU此时正访存:CPU访存结束后总线立刻交DMA

CPUDMA同时请求访存:总线交DMA

以上是关于汇编语言期末复习——第五章 模块化程序设计的主要内容,如果未能解决你的问题,请参考以下文章

华南理工大学 电力电子技术(王兆安) 期末复习笔记3 第五章第六章第七章

华南理工大学 电力电子技术(王兆安) 期末复习笔记3 第五章第六章第七章

华南理工大学 电力电子技术(王兆安) 期末复习笔记3 第五章第六章第七章

计算机网络 华南理工大学期末重点 第五章 传输层 谢希仁

2017.12.8 软件工程-----第五章 总体设计(复习)

密码学期末复习