zoukankan      html  css  js  c++  java
  • TAP任务指派问题的汇编实现

    近六周的课程设计,编了一个四百行的汇编程序,编的过程很不顺利,遇到种种意想不到的困难,但最终能够实现,可谓欣喜若狂,这期间学到了好多好多,遇到问题怎么精下心来解决,同时对汇编的理解也更加深刻了。所谓TAP任务指派问题,简单来说我实现的是有六个人,有六项任务,没个人做每一项任务的所消耗的时间代价不同,有一个六阶参考矩阵代价表,然后将六个员工编号为123456,固定不变,接下来随机产生几种任务的排序方案,假设任务命名为ABCDEF,可能随机产生一种方案为EDCABF,这意思就是第一个人做E任务,第二个人做D任务依次下去,最后计算每一种方案的总代价,然后计算每一种方案的带价总和,然和输出最优(代价值最小)的那一种方案。

    运行结果图:

     

    附源码:

    DATAS SEGMENT 
        str1 db 'reference array:','$'
        str2 db 'feasible plans:','$'
        str3 db 'How many plans do you want:(1-6) ','$'
        str4 db 'The optimal plan:','$'
        str5 db 'The order of the employees:',0dh,0ah,'123456','$'
        str6 db 'The value of these several kinds of schemes:','$'
        str7 db 'The cost of this plan is:','$'
        array db 5,6,9,7,4,6,8,3,5,4,6,7,6,2,4,7,8,9,9,7,6,8,4,5,7,4,3,6,8,9,5,7,8,9,6,4
     peo db 1,2,3,4,5,6  
     StrEnter db 0dh,0ah,'$'  ;回车换行
     n dw 1   ;用于显示数组为矩阵计数
     temp db 2  
     sii dw ?
     q db 0    ;用在计算代价值的子函数中
     save db 0 ;用于保存al的值
     best db 0  ;保存最优代价值
     chushu db 6   ;用于显示数组为矩阵作为除数
     count dw 0  ;产生随机串计数用的
     buf db 96 dup(?)  ;最多保存八种方案
     buff db 36 dup(?)  ;提取buf中有用的数字
     yy  db 8 dup(?)   ;保存六种方案的代价值
     OUTp db 0h     ;作为为调用显示函数保存的临时变量
     countr db 0    ;作为临时的和值保存
     num db 1    ;记录最小的数是第几个
    DATAS ENDS

    STACKS SEGMENT
        ;此处输入堆栈段代码
    STACKS ENDS

    CODES SEGMENT
        ASSUME CS:CODES,DS:DATAS,SS:STACKS
    START:
        MOV AX,DATAS
        MOV DS,AX
        ;此处输入代码段代码
       
        ;显示“参考数组:”
        lea dx,str1
        mov ah,9
        int 21h
        ;显示回车换行
        call CRLF        ;调用子程序
       
    ;**********************显示参考矩阵********************************************
        push si
        lea si,array
        mov cx,36   ;cx是loop的参考值
    j1: 
      mov dl,[si]
     add dl,30h
     mov ah,2    ;调用2号中断,显示单个值
     int 21h 
     mov ax,n
      div chushu 
     cmp ah,0 
       jnz tz
        call CRLF
    tz:
        inc n
        inc si
        loop j1
        pop si
        call CRLF;调用一次回车换行
    ;*****************显示员工排列的顺序******************************************
     lea dx,str5
     mov ah,9
     int 21h
     call CRLF
    ;*****************显示“你要选择多少种方案:(1-8)”*************************
    ;----显示提示语---------------------------------------------------------------   
        lea dx,str3
        mov ah,9
        int 21h
        call CRLF
    ;----输入选择----------------------------------------------------------------- 
    j2: mov ah,7
     int 21h
     cmp al,'6'
     ja j2
     cmp al,'1'
     jb j2
     mov dl,al
     mov ah,2
     int 21h
     mov save,al   ;因为下面si:步骤会更改al的值
     call CRLF
    ;*****************显示“feasible plans:”**************************************
    s1: lea dx,str2  
        mov ah,9
        int 21h
        call CRLF
    ;************************产生随机方案********************************************
     
     mov al,save
     sub al,30h  ;减去30h变成数字
     mov ah,0
     lea di,buf  ;取buf首地址
        mov cx,ax
    C0:
        call Random
        loop C0
        lea dx,buf
        mov ah,9
        int 21h
        call CRLF
    ;****************显示“这几种解决方案的代价值:”*******************************
        lea dx,str6
        mov ah,9
        int 21h

    ;********************计算每一种解决方案的值*************************************** 

        call CALCU       ;可能将save的值改变了
        call CRLF
    ;*****************显示“最优的那个方案以及其代价值”****************************
     call CRLF
     lea dx,str4
     mov ah,9
     int 21h
    ;******************计算得到最优的那个方案**************************************
     call CRLF
     ;lea dx,Str7   ;显示这最小方案的代价
        ;mov ah,9
        ;int 21h
       
     lea si,yy
     call CALBEST
    ;*******************************************************************************   
        call over  ;调用结束程序
    ;*******************************************************************************


    ;######################调用的子程序#############################################
    ;****回车换行*******************************************************************
    CRLF PROC NEAR
        lea dx,StrEnter
        mov ah,9
        int 21h
        RET
    CRLF ENDP
    ;****结束程序*******************************************************************
    OVER PROC NEAR
     MOV AH,4CH
        INT 21H
        RET
    OVER ENDP
    ;******产生随机方案******************************************************************
    ;入口为 di,将di后的六位填充六个随机数
    Random proc near
     push cx
     push si
        mov sii,di
        mov cx,6
    L3:
     push cx
    L0:
        xor ax,ax
        out 43h,al
        in al,40h
        cmp al,1
        jb L0
        cmp al,6
        ja L0
        or al,40h
        mov si,sii   
        mov [di],al   
        mov ax,di
        cmp ax,si
        jz L2
        sub ax,si 
        mov cx,ax
    L1:   
        mov ah,[si]
        cmp ah,[di]
        jz L0
        inc si
        loop L1  
    L2:
        pop cx
        inc di
        loop L3 
        mov [di],0dh
        inc di
        mov [di],0ah
        inc di
        mov [di],'$'
        pop si
        pop cx      
        ret
    Random endp

    ;****计算代价值*****************************************************************
    ;入口:peo db 6       buf db 96    array(参考数组) db   save db (保存几个方案)
    ;出口:res dw 8(保存所有方案的代价值)
    CALCU PROC NEAR       ;g97
     push si
     push di    ;<<
        push bp
     call CRLF
     call CONVERTBUFTOBUFF  ;将buf中的有用数据存到buff中
     lea si,yy   ;保存六种方案的代价值
     mov q,0    ;大循环的判断条件    db
    f0:;将指针指向缓冲区的头部
     lea di,buff
     
     mov ah,0      ;控制到buff中的第几个方案的头地址
     mov al,q
     mul chushu    ;乘以6
     add di,ax     ;fla标记是将si和di指向两个头指针
     
     mov ax,0
     mov ch,0   ;小循环的判断条件
    fl: 
        inc ax
    push ax     ;>>
     dec ax
     mul chushu     ;(x-1)*6+y       (chushu=6)
     mov bl,[di]
     mov bh,0 
     add ax,bx   ;计算要参考代价表的第几个值存在ax中
     lea bp,array    ;参考代价表
     dec ax       ;自减一下,因为没从0开始
     add bp,ax
     mov dl,[bp]    ;取参考表的值到dl
     mov dh,0
        add countr,dl   ;和值不断增加   
     inc di
    pop ax
     inc ch
     cmp ch,chushu   ;判断是否循环了六次
     JNE fl
     mov dl,countr  ;把一种方案的六次的值放到dl中然后赋给
     mov [si],dl    ;将计算的结果压到yy
     mov dl,[si]
     mov OUTp,dl
     call OUTPut
     
     inc si;*;
     mov countr,0   ;和重新清0,重新计算下一个方案的结果值
        ;mov dl,[si]  
        ;mov OUTp,dl;<<  ;将和赋给OUTp,方便输出
        ;call OUTPut     ;输出显示
       
        inc q
     mov al,q
     cmp al,save    ;比较大循环和save的值 看看是否结束
     JNE f0
     pop bp
     pop di
     pop si
     RET
    CALCU ENDP
    ;***计算最小的那个代价值*******************************************************
    ;入口 res dw 8
    ;出口 best dw
    CALBEST PROC NEAR 
     push si
     mov bl,1      ;记录最小的这个代价值是yy中的第几个
     
     mov cl,save      ;控制循环几次
     dec cl
     mov ch,0
     ;mov dx,cx   ;验证save是否正确
     ;add dx,30h
     ;mov ah,2
     ;int 21h
    ;;;;;;;;;;验证压入YY的值是否正确;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
        mov dl,[si]
        mov best,dl
        cmp cx,0 ;如果save等于0,则不要比较直接跳转结束        
        jz q3
     
     inc si
    q1: 
     mov dl,[si]
     ;add dx,30h
     ;mov ah,2
     ;int 21h
     inc bl    ;记录是数组中的第几个,以便输出那个方案
     cmp dl,best
     jnb q2     ;大于或等于则跳转到q2
     mov best,dl
     mov num,bl
    q2: 
     inc si    ;si加一是字节,如果保存的是dw类型的就要加2
     loop q1
     
     ;此时已经计算好了dl和最小的值,接下来时显示
    q3: 
     mov dl,num   ;第几个方案最小
     add dl,30h
     mov ah,2
     int 21h
     call CRLF
     
     ;依次输出这六个方案
     ;mov dl,num
     ;add dl,30h
     ;mov ah,2
     ;int 21h
     mov dl,num
     push di
     lea di,buff
     mov dh,0
     dec dl
     mov al,dl
     mov ah,0
     mul chushu
     add di,ax
     
     ;显示最优方案的六个字母
     mov cx,6
    q10:
     mov dl,[di]
     add dl,40h
     mov ah,2
     int 21h
     inc di
     loop q10
     pop di
     call CRLF
     
     ;显示这最小方案的代价的提示语
     lea dx,Str7  
        mov ah,9
        int 21h
       
     mov dl,best   ;显示最小方案的代价值
     mov OUTp,dl
     call OUTPut
        pop si
     RET
    CALBEST ENDP

    ;*****将buf中的值去掉回车换行存到buff***********************************************************
    CONVERTBUFTOBUFF PROC NEAR
    push si
     sub save,30h
        mov al,save
        mov ah,0
        mov bl,6
        mul bl      ;控制多少次循环
     mov cx,ax
     mov bx,0
     lea si,buf
     lea di,buff
    q4: mov dl,[si]
     sub dl,40h
     mov [di],dl
     inc si
     inc di
     inc bx
     cmp bx,6
     JNE q5
     add si,2
     mov bx,0
    q5: loop q4
    pop si
     RET
    CONVERTBUFTOBUFF ENDP
    ;******将一个字节型的OUTp输出显示**********************************************
    OUTPut proc       ;字节型的OUTp两位数的和
        push si
        lea si,temp
        mov al,OUTp
        mov cx,1
        mov bl,10
    CX1:
        cmp al,10
        jb  CX2    ;小于跳转
        sub ah,ah  ;清0
        div bl
        mov [si],ah  ;余数赋给
        inc si
        inc cx
        sub ah,ah   ;余数部分清0
        jmp CX1
           
    CX2:
     mov [si],al  ;商赋给
    CX3:
     mov dl,[si]  ;商显示
        add dl,30h
        mov ah,2
     int 21h
     dec si      ;自减1,然后显示余数
     loop CX3;   ;循环两次 将商和余数显示出来
     mov dl,' '
     int 21h
        pop si
        RET
    OUTput endp
    ;******************************************************************************
    CODES ENDS
        END START

      

    详细报告请参见:http://download.csdn.net/detail/s10141303/4980981

  • 相关阅读:
    使用sudo crontab修改Linux系统时间
    Redis缓存雪崩和穿透的解决方法
    设计模式之委托模式
    设计模式之模板模式
    并发编程面试题
    AQS之共享锁实现原理
    AQS之独占锁实现原理
    CentOS 7.1 Bridge启用STP报错"Master connection not found or invalid"
    nginx反向代理docker registry报”blob upload unknown"解决办法
    [转]Linux df 命令不更新磁盘数据空间使用情况的解决办法
  • 原文地址:https://www.cnblogs.com/java20130723/p/3211489.html
Copyright © 2011-2022 走看看