目錄
目的與要求
内容與方法
步驟與過程
程式總體設計
核心資料結構——冒泡排序
調試過程
成績資料檔案data編寫和程式資料初始
成績複制
冒泡排序
A B計數儲存
核心代碼
結論或體會
目的與要求
分析和了解實驗指定的問題
利用LC-3的彙編代碼設計實作相關程式
熟練掌握循環、分支程式設計方法
内容與方法
- 背景
- 16名學生成績排序,及統計分析
- 成績分類規則
- A:全班排名前25%,且成績在85分及以上
- B:非A成績,全班排名前50%,且成績在75分及以上
- C:非A、B成績
- 要求
- 使用LC-3彙編語言,編寫程式實作以上功能
- 輸入
- 16名學生成績,存儲于x3200至x320F
- 每個成績為0至100之間,由16比特無符号整數表示
- 輸出
- 成績降序排序,并存儲于x4000至x400F記憶體位置,x4000位置成績為最高成績
- 得A、B成績的學生總人數,分别存儲于x4100,及x4101位置
步驟與過程
程式總體設計
- 根據題目,首先要實作的是成績的存儲。首先我用标号SCORE存儲成績首位址x3200,用data檔案記錄16個成績于起始位置:.ORIG x3200。
- 其他重要位址和常量用标号表示如下:
SCORE .FILL x3200 ;成績存放起始位址
RES .FILL x4000 ;成績降序結果存放起始位址
Anum .FILL x4100 ;存放A位址
Bnum .FILL x4101
nAscore .FILL -85 ;A分數相反數
nBscore .FILL -75
StuNUM .FILL 16 ;學生人數
ONE .FILL 1 ;1
- 算法流程——具體實作步驟如下:
- 将成績複制到結果區:COPY循環
- 冒泡排序:2層嵌套循環
- 計算A B人數:各2個循環(CountA CountB)
- 結果儲存:STORE
核心資料結構——冒泡排序
C++代碼如下:
for(int i=1;i<n;i++){
For(int j=0;j<n-I;j++){
If(score[j]<score[j+1]){
Swap(score[j],score[j+1])
}
}
}
調試過程
因為程式步驟較多,我進行分子產品編寫和調試,逐漸完成。
成績資料檔案data編寫和程式資料初始
- 代碼編寫編譯(圖1)
R1存成績存放初始位址SCORE(x3200),R7存結果降序成績初始位址RES(x4000)。标号編寫。

Figure 1 data編寫和程式資料初始
- 運作結果無誤(圖2)
Figure 2 資料獲得和初始成功
成績複制
先将成績直接複制到結果區,在結果區排序。
- 編寫編譯運作(圖3)
Figure 3 成績複制代碼編譯運作
- 結果正确,x3200和x4000存放的資料一樣(圖4)
Figure 4 成績複制成功
冒泡排序
- 編譯通過(圖5)
Figure 5 冒泡成功編譯運作
- 答案錯誤,代碼有誤,經過單步調試發現是每輪冒泡循環沒有把成績指針指向首位。(圖6)
Figure 6 調試過程
- 修改代碼(圖7)
每次循環都初始成績指針指向第一個成績。修改後答案正确
Figure 7 修改冒泡排序
A B計數儲存
2個循環CountA和CountB周遊前4和前8個數,獲得A B人數,并儲存。(圖8)
Figure 8 程式結果正确
核心代碼
.ORIG x3000 ;程式開始
LD R1,SCORE ;R1為存放成績初始位址
LD R7,RES ;R7存放成績降序結果位址
LD R2,StuNUM ;R2裝入學生人數
;
; 成績複制至結果區(loop)
;
COPY LDR R3,R1,0 ;R3存成績
STR R3,R7,0 ;成績存結果
ADD R1,R1,1 ;下一個成績
ADD R7,R7,1 ;結果成績指針移向下一個
ADD R2,R2,-1 ;計數減1
BRp COPY ;繼續循環直至全部複制
; 冒泡排序
;
LD R2,ONE ;R2初始1,外層循環i,輪次
;
; 外層循環LOOP1(R2 0<i<n)
LOOP1
; 内層循環(R3 0<=j<n-i)
;
LD R7,RES ;R7存放成績降序結果首位址
AND R3,R3,0 ;R3清零, 裡層循環j,下标
ADD R1,R2,-16 ;R1=-(n-i)
LOOP2 LDR R4,R7,0 ;R4存SCORE[j]
LDR R5,R7,1 ;R5存SCORE[j+1]
NOT R6,R4
ADD R6,R6,1
ADD R6,R6,R5 ;R6=SCORE[j+1]-SCORE[j]
BRnz FLAG ;如果SCORE[j+1]<=SCORE[j],不用交換直接跳過
;
; 交換SCORE[j+1] SCORE[j]
;
STR R5,R7,0
STR R4,R7,1
;
FLAG
ADD R7,R7,1 ;指向下一成績
ADD R3,R3,1 ;j++
ADD R6,R3,R1 ;R6=j-(n-i)
BRn LOOP2 ;如果j<n-i,繼續内層循環
;
; 内層循環結束
ADD R2,R2,1
ADD R6,R2,-16;R6=i-n
BRn LOOP1 ;如果i<n,繼續外層循環
;
; 外層循環結束,冒泡排序完成
; 計數A B人數
;
LD R2,nAscore ;R2=-85
LD R3,nBscore
AND R1,R1,0 ;R1清零,計數
AND R5,R5,0 ;R5清零存A人數
AND R6,R6,0 ;B人數
LD R7,RES ;R7存放成績降序結果首位址
;
; 獲得的A人數
;
CountA LDR R4,R7,0
ADD R4,R4,R2 ;R4=score-85
BRn CountB ;如果score<85,開始計數B
ADD R5,R5,1 ;人數增加
ADD R7,R7,1 ;移向下一分數
ADD R1,R1,1 ;計數加1
ADD R0,R1,-4 ;R0=計數-4
BRn CountA ;計數小于4,還在前25%繼續判斷A人數
;
; 獲得B的人數
;
CountB LDR R4,R7,0
ADD R4,R4,R3 ;R4=score-75
BRn STORE ;如果score<75,跳出B計數,進行儲存
ADD R6,R6,1 ;人數增加
ADD R7,R7,1 ;移向下一分數
ADD R1,R1,1 ;計數加1
ADD R0,R1,-8 ;R0=計數-8
BRn CountB ;計數小于8,還在前50%繼續判斷B人數
;
; 将A B人數儲存
;
STORE STI R5,Anum
STI R6,Bnum
HALT ;程式運作結束
;
SCORE .FILL x3200 ;成績存放起始位址
RES .FILL x4000 ;成績降序結果存放起始位址
Anum .FILL x4100 ;存放A位址
Bnum .FILL x4101
nAscore .FILL -85 ;A分數相反數
nBscore .FILL -75
StuNUM .FILL 16 ;學生人數
ONE .FILL 1 ;1
;
.END ;代碼結束
結論或體會
在本次實驗中,我首次嘗試了在LC3利用彙編代碼實作一個小程式,熟悉了了相關文法和良好的代碼分割。認識到了适用标号的諸多好處,如利用LD直接加載資料常量,将位址偏移的計算交給機器負責進而增加代碼的可讀性;同時也熟悉了關于标号的各種操作。通過規定檔案起始位置(.ORIG)實作多檔案連接配接的可能。
另外我熟悉了利用彙編代碼編寫循環和分支結構的過程,第一次嘗試用彙編代碼實作冒泡排序。嘗試了将一個實際問題通過問題分析,找到相應的算法實作流程及資料結構,進而通過逐漸編寫調試完成對問題的解決。
在本次實驗中我也糾正了一些自己的模糊認知。比如标号位址是一個常量,不能做指針移動。其他資料标号也同樣是常量,需要将其指派給寄存器才能進行變量操作。另外lc3僅有8個寄存器。需要合理循環利用寄存器。