80*86組合語言學生成績排序系統
五、實驗結果及分析
1、實驗執行過程及分析
(1)選單:
主要程式碼:
在輸出選單之前首先使用清屏效果,以下為清屏效果的原始碼:
MOV AH,15
INT 10H
MOV AH,0
INT 10H
之後呼叫巨集指令輸出選單,並呼叫選擇輸入子程式:
OUTPUT_AH_9 CATALOG_1
:
:
OUTPUT_AH_9 CATALOG_6
CALL INPUT_CHOICE ; 呼叫選擇輸入子程式
用BUTTON判斷是否需要再次迴圈,比較BUTTON是否為1,如果輸入ESC,則退出選單迴圈結束程式,如果BUTTON為0,則迴圈輸出選單。
CMP BUTTON,1
JNE OUTPUT_CATALOG
(2)輸入功能:
主要程式碼:
通過迴圈判斷NAME_BUF[SI+2]中的值是否為回車,若不是,則將該名字傳送到用來儲存資料的空間NAME_GRADE_SAVE中。
LOOP_INPUT_NAME:
MOV AL, NAME_BUF[SI+2]
CMP AL,13
JE INPUT_GRADE
MOV NAME_GRADE_SAVE [DI][BX],AL
INC SI
INC BX
LOOP LOOP_INPUT_NAME
通過迴圈判斷NAME_BUF[SI+2]中的值是否為回車,若不是,則將該成績傳送到用來儲存資料的空間NAME_GRADE_SAVE中。
LOOP_INPUT_GRADE:
MOV AL,GRADE_BUF[SI+2]
CMP AL,13
JE AGAIN
MOV NAME_GRADE_SAVE[DI][BX],AL
INC SI
INC BX
LOOP LOOP_INPUT_GRADE
最後輸出一個值進行判斷,若值為”y”,則迴圈到輸入名字之前再次輸入名字,若值為”n”,則退出該輸入子程式。
OUTPUT_AH_9 TIP_5
MOV AH,1
INT 21H
CMP AL,"y"
JE INPUT
CMP AL,"n"
JE INPUT_OUT
OUTPUT_AH_9 TIP_2
JMP AGAIN
(3)輸出功能:
主要程式碼:
用2號功能依次迴圈輸出名字,當判斷下一個地址的值為’$’時停止輸出;並在迴圈的同時使變數NAME _LONG的值自加1,以便之後輸出空格。
LOOP_OUTPUT_NAME:
MOV AL,NAME_GRADE_SAVE[DI][BX]
CMP AL,'$'
JE LOOP_OUTPUT_NAME_END
MOV DL,AL
MOV AH,2
INT 21H
INC BX
INC NAME_LONG
JMP LOOP_OUTPUT_NAME
根據名字的長度確定應該輸出多少個空格,並迴圈輸出空格。
MOV AL,14
SUB AL,NAME_LONG
PUSH CX
MOV CX,0
MOV CL,AL
LOOP_KONGGE_1:
KONGGE
LOOP LOOP_KONGGE_1
用2號功能依次迴圈輸出成績的值,當判斷下一個地址的值為’$’時停止輸出;並在迴圈的同時使變數GRADE_LONG的值自加1,以便之後輸出空格。
LOOP_OUTPUT_GRADE:
MOV AL,NAME_GRADE_SAVE[DI][BX]
INC GRADE_LONG
CMP AL,'$'
JE LOOP_OUTPUT_GRADE_END
MOV DL,AL
MOV AH,2
INT 21H
INC BX
JMP LOOP_OUTPUT_GRADE
根據成績的長度確定應該輸出多少個空格,並迴圈輸出空格。
MOV AL,14
SUB AL,GRADE_LONG
PUSH CX
MOV CX,0
MOV CL,AL
LOOP_KONGGE_2:
KONGGE
LOOP LOOP_KONGGE_2
將變數MINGCI每次迴圈時自加1,並在輸出完名字和成績之後輸出該變數作為名次。
MOV DL, MINGCI
MOV AH,2
INT 21H
INC MINGCI
(4)排序功能:
主要程式碼:
用迴圈求出每個成績的長度,當執行到’$’時,停止迴圈。
LOOP_SIZE:
INC GRADE_LONG
INC SI
CMP NAME_GRADE_SAVE[BX][SI],'$'
JNE LOOP_SIZE
比較前一個成績和後一個成績,若前一個大於後一個,則跳轉到交換結束(即不交換),若前一個小於後一個,則跳轉到交換的程式。
MOV AL,GRADE_LONG
CMP GRADE_MAX_LONG,AL
JA COMPARE_END
JB SORT_SHORT_CHANGE
若輸入的兩個數相等,則依次從高位到低位一個一個進行比較,若前者比後者小,則交換,若後者比前者小,則不交換,若相等,則繼續迴圈。
LOOP_COMPARE:
MOV AL,NAME_GRADE_SAVE[BX][SI]
CMP NAME_GRADE_SAVE[BX][DI],AL
JA COMPARE_END
JB SORT_CHANGE ;前者比後者小,交換
INC SI
INC DI
CMP NAME_GRADE_SAVE[BX][DI],'$'
JNE LOOP_COMPARE
JMP COMPARE_END
將SI和DI各減小10,指向名字的第一個位置,迴圈20次,將整個儲存學生名字和成績的單位全部依次交換。
SUB SI,10
SUB DI,10
MOV CX,20
LOOP_SORT_CHANGE:
MOV AL,NAME_GRADE_SAVE[BX][SI]
XCHG AL,NAME_GRADE_SAVE[BX][DI]
XCHG AL,NAME_GRADE_SAVE[BX][SI]
INC SI
INC DI
LOOP LOOP_SORT_CHANGE
2、執行結果
圖1:(選單和輸入效果)
圖2:(直接輸出效果)
圖:3:(排序程式執行後結果)
圖4:(排序後輸出結果)
圖5:(求最大值輸出結果)
3、心得體會
通過本次綜合實驗,我對彙編程式的操作指令有了更加細緻的認識。由於本次實驗的實驗目的是完成一個學生成績管理系統,因此需要實現對學生成績的排序,這也是本次實驗的難點之一。在進行排序時,必須要實現名字與成績同時運動,雖然我們之前已經進行過對數字的氣泡排序,但那只是對數字進行交換,沒有考慮姓名的同步性問題。在解決這個問題時,我的方法是用20個位元組的儲存單元來儲存單個學生的個人資訊,而當判斷出成績大小需要交換時,我將指標移到單個學生和他下一個學生的第一個單元,然後迴圈20次,直接將一整塊資訊都進行交換。
另外一個難點是對學生成績輸入的處理,因為本次實驗的要求是不定位數成績輸入,我想到了兩種思路,一種是常規思路,每輸入一個數時,將臨時儲存單位temp(初值為0)中的數值乘10,再加上剛剛輸入的那個數,這樣的好處在於無論我輸入多少個數,最終的結果一定與我實際想要得到的數相同。另一種思路是不將它轉換成實際的數,而是將輸入的數當作字串處理,這樣使輸入輸出變得更加簡單了,但是當我在進行比大小的操作時就變得相對複雜了,因為我必須要首先比較兩個數的長短,如果相等的話再從高位向低位依次比較大小,比兩個數字直接比大小複雜了很多。
最後,通過本次綜合實驗,我真的學習到了很多,而且說實話我找錯誤和發現記憶體異常的能力變得更強了,這都得益於這次綜合實驗中遇到的問題和bug。總之,本次綜合實驗讓我收穫頗豐。