本文共 6852 字,大约阅读时间需要 22 分钟。
近六周的课程设计,编了一个四百行的汇编程序,编的过程很不顺利,遇到种种意想不到的困难,但最终能够实现,可谓欣喜若狂,这期间学到了好多好多,遇到问题怎么精下心来解决,同时对汇编的理解也更加深刻了。所谓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 ENDSSTACKS SEGMENT
;此处输入堆栈段代码 STACKS ENDSCODES 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
详细报告请参见:
本文转自蓬莱仙羽51CTO博客,原文链接:http://blog.51cto.com/dingxiaowei/1366630,如需转载请自行联系原作者