1. 程式人生 > >彙編實現氣泡排序

彙編實現氣泡排序

1.輸入部分實現

;下面是寫入過程,各暫存器存的東西:
;AX 用於DOS呼叫,然後還用於*10,/10之後存放結果
;BX 用於記錄存了多少個數(每個數2位元組16位)
;CX 存放SHL、SHR的移動次數(超過1要放在CL裡)
;DX 用於存放得到每個數之前的臨時值
NNUM:;先把當前數字放入記憶體,然後使BX+2,然後下一個數字的開始(到NEXT)
	; MOV CL,4
	; SHR DX,CL		
	MOV [BX],DX
	ADD BX,2
	MOV DX,0
	;這裡要讓AL=0,DX=0,防止NEXT的第一句將數字*10對輸入的第一個字元起作用
NEXT:
	;輸入下一個數字
	MOV AH,1
	INT 21H
	;對輸入的數進行判定,看是否是空格或者回車
	CMP AL,'.'		;如果是回車符號,則證明輸入完了
	JZ SORTSTART	;結尾的話跳到SORT部分排序
	CMP AL,' '
	JZ NNUM		;如果是空格,則證明當前輸入完了,將CX裡的數字放到儲存器中去
	;對之前的數字的高位數字調整,壓縮BCD
	MOV CL,4
	SHL DX,CL
	;加入這次的個位數
	SUB AL,30H		;-30H得到對應的數字
	ADD DL,AL	
	JMP NEXT		;如果不是空格,證明當前元素沒輸入完,則再次檢測輸入當前數字的下一位

2.排序部分實現

利用雙層LOOP配合堆疊段實現

;上面完成了存入資料的操作,下面是排序的操作,各暫存器的內容:
;AX 存放交換的第一個數字
;BX 沒用到,依舊保留原來的數值,即入讀數的數量*2
;CX 內、外迴圈的次數,內迴圈完了出棧
;DX 沒用到
SORTSTART:
	MOV AX,DATA 	
	MOV DS,AX
	MOV AX,BX
	SHR AX,1		;內容/2,得到數字個數
    MOV CX,AX        ;外層迴圈AX趟
	; DEC CX 			;初始化次數n為總數AX-1,因為需要內迴圈迴圈執行n-1次,不然會在第一次迴圈的時候,將最後一個數和陣列以外的內容比較並交換,使得丟失資料
;這裡是外層迴圈
FORI:  
	PUSH CX          ;儲存外層迴圈次數
    ;注意到外層第1次迴圈,內迴圈執行CX-1次,外層第2次迴圈,內迴圈執行CX-2次,...控制外迴圈的cx值恰就是內層迴圈次數
    MOV SI, 0        ;相當於內層迴圈時取陣列內容的指標
;這裡是內層迴圈
FORJ:
	MOV AX, [SI]     ;(ax)即a[j]
    CMP AX, [SI+2]   ;a[j]與a[j+1]比較
    JBE NEXTNUM      ;a[j]<=a[j+1]時	,跳到下一步NEXTNUM不交換
    XCHG AX, [SI+2]  ;交換
    MOV [SI], AX     ;最終效果是a[j]與a[j+1]交換了
;迴圈控制和轉跳部分
NEXTNUM: 
	ADD SI, 2        ;下一個數,j++
    lOOP FORJ	     ;內層迴圈,使得CX--,然後再次執行,直到CX=0
    POP CX           ;恢復外層迴圈的CX,相當於當前的內層for(j)結束了,執行外層的fori
    lOOP FORI        ;外層迴圈

 

 

3.實現輸出過程

單獨處理每兩個位元組的四位數字的壓縮BCD顯示,利用CH作為內迴圈的i,'$'作為外迴圈的判斷

;這裡是最後的顯示
OUT_ALL:
	;為了保證最後一個數字的正確錄入,要求手動輸入最後一個數字之後,先' '後'回車'
	MOV DL,13	;回車 結尾
	MOV AH,2
	INT 21H
	MOV DL,10	;換行
	MOV AH,2
	INT 21H		;AH=2 單獨顯示DL的內容
	MOV BYTE PTR [BX],'$';結尾加上結尾符號標誌

	MOV CX,BX
	MOV SI,0
SHOW:
	MOV DL,32	;空格 用於顯示下一個數字
	MOV AH,2
	INT 21H
	MOV BX,[SI]
	ADD SI,2		;指向下一個位元組的內容
	CMP BL,'$'
	JZ EXIT 		;設定出口
	MOV CL,4 		;CL是用在下面的SHL部分
	MOV CH,4 		;用於內層迴圈
;單獨處理每兩個位元組的四位數字顯示
BYTE1:
	MOV DX,BX
	AND DX,0F000H 	;僅保留最高四位
	SHR DH,CL   	;挪到DH的低四位
	MOV DL,DH
	ADD DL,30H 		;DL存放的恰好是所需要的ASC碼
	MOV AH,2
	INT 21H
	SHL BX,CL		;將BX左移4位,把最高位讓給下個字元
	DEC CH
	CMP CH,0
	JNZ BYTE1		;內層迴圈
	JMP SHOW

 

 

4.下面是完整的程式碼:

DATA SEGMENT
	BUFFER DB 20 DUP(0FFH)
	;定義資料段,放入20個FFH位元組,DPU()相當於malloc(x),用於寫入資料
DATA ENDS

;使用預設堆疊段

CODE SEGMENT
	ASSUME CS:CODE,DS:DATA
	;程式碼段
	;設定程式碼段和資料段的段基地址

;各暫存器存的東西:
;AX 用於DOS呼叫,然後還用於*10之後存放結果
;BX 用於記錄存了多少個數(每個數2位元組16位)
;CX 用於存放得到每個數之前的臨時值
;DX 在EXIT中用作移入結束符號和換行等等,在NEXT中DL用於存放*10放到AX裡

START:
	MOV AX,DATA 	
	MOV DS,AX
	MOV BX,OFFSET BUFFER
	MOV DX,0
	MOV AX,0
	JMP NEXT



;下面是寫入過程,各暫存器存的東西:
;AX 用於DOS呼叫,然後還用於*10,/10之後存放結果
;BX 用於記錄存了多少個數(每個數2位元組16位)
;CX 存放SHL、SHR的移動次數(超過1要放在CL裡)
;DX 用於存放得到每個數之前的臨時值
NNUM:;先把當前數字放入記憶體,然後使BX+2,然後下一個數字的開始(到NEXT)
	; MOV CL,4
	; SHR DX,CL		
	MOV [BX],DX
	ADD BX,2
	MOV DX,0
	;這裡要讓AL=0,DX=0,防止NEXT的第一句將數字*10對輸入的第一個字元起作用
NEXT:
	;輸入下一個數字
	MOV AH,1
	INT 21H
	;對輸入的數進行判定,看是否是空格或者回車
	CMP AL,'.'		;如果是回車符號,則證明輸入完了
	JZ SORTSTART	;結尾的話跳到SORT部分排序
	CMP AL,' '
	JZ NNUM		;如果是空格,則證明當前輸入完了,將CX裡的數字放到儲存器中去
	;對之前的數字的高位數字調整,壓縮BCD
	MOV CL,4
	SHL DX,CL
	;加入這次的個位數
	SUB AL,30H		;-30H得到對應的數字
	ADD DL,AL	
	JMP NEXT		;如果不是空格,證明當前元素沒輸入完,則再次檢測輸入當前數字的下一位




;上面完成了存入資料的操作,下面是排序的操作,各暫存器的內容:
;AX 存放交換的第一個數字
;BX 沒用到,依舊保留原來的數值,即入讀數的數量*2
;CX 內、外迴圈的次數,內迴圈完了出棧
;DX 沒用到
SORTSTART:
	MOV AX,DATA 	
	MOV DS,AX
	MOV AX,BX
	SHR AX,1		;內容/2,得到數字個數
    MOV CX,AX        ;外層迴圈AX趟
	; DEC CX 			;初始化次數n為總數AX-1,因為需要內迴圈迴圈執行n-1次,不然會在第一次迴圈的時候,將最後一個數和陣列以外的內容比較並交換,使得丟失資料
;這裡是外層迴圈
FORI:  
	PUSH CX          ;儲存外層迴圈次數
    ;注意到外層第1次迴圈,內迴圈執行CX-1次,外層第2次迴圈,內迴圈執行CX-2次,...控制外迴圈的cx值恰就是內層迴圈次數
    MOV SI, 0        ;相當於內層迴圈時取陣列內容的指標
;這裡是內層迴圈
FORJ:
	MOV AX, [SI]     ;(ax)即a[j]
    CMP AX, [SI+2]   ;a[j]與a[j+1]比較
    JBE NEXTNUM      ;a[j]<=a[j+1]時	,跳到下一步NEXTNUM不交換
    XCHG AX, [SI+2]  ;交換
    MOV [SI], AX     ;最終效果是a[j]與a[j+1]交換了
;迴圈控制和轉跳部分
NEXTNUM: 
	ADD SI, 2        ;下一個數,j++
    lOOP FORJ	     ;內層迴圈,使得CX--,然後再次執行,直到CX=0
    POP CX           ;恢復外層迴圈的CX,相當於當前的內層for(j)結束了,執行外層的fori
    lOOP FORI        ;外層迴圈





;這裡是最後的顯示
OUT_ALL:
	;為了保證最後一個數字的正確錄入,要求手動輸入最後一個數字之後,先' '後'回車'
	MOV DL,13	;回車 結尾
	MOV AH,2
	INT 21H
	MOV DL,10	;換行
	MOV AH,2
	INT 21H		;AH=2 單獨顯示DL的內容
	MOV BYTE PTR [BX],'$';結尾加上結尾符號標誌

	MOV CX,BX
	MOV SI,0
SHOW:
	MOV DL,32	;空格 用於顯示下一個數字
	MOV AH,2
	INT 21H
	MOV BX,[SI]
	ADD SI,2		;指向下一個位元組的內容
	CMP BL,'$'
	JZ EXIT 		;設定出口
	MOV CL,4 		;CL是用在下面的SHL部分
	MOV CH,4 		;用於內層迴圈
;單獨處理每兩個位元組的四位數字顯示
BYTE1:
	MOV DX,BX
	AND DX,0F000H 	;僅保留最高四位
	SHR DH,CL   	;挪到DH的低四位
	MOV DL,DH
	ADD DL,30H 		;DL存放的恰好是所需要的ASC碼
	MOV AH,2
	INT 21H
	SHL BX,CL		;將BX左移4位,把最高位讓給下個字元
	DEC CH
	CMP CH,0
	JNZ BYTE1		;內層迴圈
	JMP SHOW



EXIT:
	MOV AH,4CH
	INT 21H  		
CODE ENDS			
	END START