冒泡排序的匯編語(yǔ)言與C語(yǔ)言程序?qū)Ρ?/h1>
# include?<stdio.h>
int?main(void)
{
int?i,?j;?//循環(huán)變量
int?MinIndex;?//保存最小的值的下標(biāo)
int?buf;?//互換數(shù)據(jù)時(shí)的臨時(shí)變量
int?a[]?=?{5,?5,?3,?7,?4,?2,?5,?4,?9,?1,?8,?6};
int?n?=?sizeof(a)?/?sizeof(a[0]);?//存放數(shù)組a中元素的個(gè)數(shù)
for?(i=0;?i<n-1;?++i)?//n個(gè)數(shù)比較n-1輪
{
MinIndex?=?i;
for?(j=i+1;?j<n;?++j)?//每輪比較n-1-i次, 找本輪最小數(shù)的下標(biāo)
{
if?(a[MinIndex]?>?a[j])
{
MinIndex?=?j;?//保存小的數(shù)的下標(biāo)
}
}
if?(MinIndex?!=?i)?/*找到最小數(shù)之后如果它的下標(biāo)不是i則說(shuō)明它不在最左邊, 則互換位置*/
{
buf?=?a[MinIndex];
a[MinIndex]?=?a[i];
a[i]?=?buf;
}
}
printf("最終排序結(jié)果為:\n");
for?(i=0;?i<12;?++i)
{
printf("%d ",?a[i]);
}
printf("\n");
return?0;
}
以上是C語(yǔ)言程序
;用匯編語(yǔ)言實(shí)現(xiàn)實(shí)現(xiàn)冒泡排序,并將排序后的數(shù)輸出
DATAS SEGMENT
A dw 5, 5, 3, 7, 4, 2, 5, 4, 9, 1, 8, 6
N=$-A ;計(jì)算數(shù)字所占的字節(jié)數(shù)
DATAS ENDS
//相當(dāng)于int a[] = {5, 5, 3, 7, 4, 2, 5, 4, 9, 1, 8, 6};//
CODES?SEGMENT
ASSUME?CS:CODES,DS:DATAS
START:MOV?AX,DATAS
MOV?DS,AX // 相當(dāng)于int?a[]?中的數(shù)組a獲得了一個(gè)確切的起始地址
MOV?SI,0?;SI遍歷數(shù)字;前一個(gè)數(shù)的地址
MOV?CX,N/2-1?;設(shè)置循環(huán)次數(shù),M(M=N/2)個(gè)數(shù)需要,循環(huán)M-1次
CALL BUBBLE?;調(diào)用BUBBLE將原來(lái)的數(shù)排序
;輸出排序后的數(shù)
MOV?CX,N/2?;循環(huán)M次輸出排序后的M個(gè)數(shù)
MOV?SI,0?;SI遍歷排序后的數(shù)
MOV?DI,0?;用DI記錄數(shù)字的位數(shù)
MOV?BP,N+5?;BP用于遍歷存儲(chǔ)的轉(zhuǎn)化后的字符的位置(因?yàn)槊總€(gè)數(shù)字占4個(gè)字節(jié),中間一個(gè) 空格)
SHOW:?PUSH?CX?;循環(huán)次數(shù)入棧
MOV?DX,0?;由于將要進(jìn)行16位除需要置高16位為0
MOV?AX,[SI]?;低16位為排序后的數(shù)
CALL DTOC?;調(diào)用DTOC將十進(jìn)制數(shù)轉(zhuǎn)換為字符串
CALL SHOW_STR?;調(diào)用SHOW_STR將一個(gè)數(shù)轉(zhuǎn)化得到的字符串輸出
ADD?SI,2?;下一個(gè)數(shù)
POP?CX?;循環(huán)次數(shù)出棧棧
LOOP SHOW
MOV?AH,4CH 匯編語(yǔ)言先要將每一個(gè)排好序的數(shù)字轉(zhuǎn)換為字符串,然后再在屏幕上顯示
INT 21H
整個(gè)上面這一段相當(dāng)于for (i=0; i<12; ++i)
{printf("%d ", a[i]);}
;冒泡排序
BUBBLE PROC
L1: PUSH CX ;將循環(huán)次數(shù)入棧
LEA SI,A ;SI遍歷DATAS數(shù)據(jù)段的數(shù)字
L2: MOV AX,A[SI] ;將前一個(gè)數(shù)存于AX
CMP AX,A[SI+2] ;比較前后兩個(gè)數(shù)
JBE NEXT ;如果前一個(gè)數(shù)小于或等于后一個(gè)數(shù)則繼續(xù)本輪的比較
XCHG AX,A[SI+2] ;否則,交換前后兩個(gè)數(shù)的位置
MOV A[SI],AX
NEXT:ADD SI,2 ;下一個(gè)數(shù)
LOOP L2 ;注意內(nèi)層循環(huán)的次數(shù)已經(jīng)確定了
POP CX ;將循環(huán)次數(shù)出棧
LOOP L1 ;下一輪比較
RET
BUBBLE ENDP
//整個(gè)過(guò)程與C語(yǔ)言中的冒泡過(guò)程一樣。注意兩者的指針差別:C語(yǔ)言中就是簡(jiǎn)單的整型變量
i,j,而匯編語(yǔ)言則要指定具體是哪個(gè)寄存器//
; 將十進(jìn)制數(shù)轉(zhuǎn)換為字符串并儲(chǔ)存起來(lái)
DTOC PROC
S:MOV CX,10 ;將除數(shù)10,放入CX中
CALL DIVDW ;調(diào)用DIVDW程序
ADD CL,30H ;把數(shù)字轉(zhuǎn)換為ASCII碼,這樣就能顯示了
MOV DS:[BP],CL ;把ASCII碼放到內(nèi)存中
INC DI ;用DI記錄循環(huán)的次數(shù)
PUSH AX ;將低16位入棧
ADD AX,DX ;將高位與低位相加,接著判斷是否已經(jīng)除盡
JZ BACK ;除盡后返回調(diào)用處
POP AX ;將低16位出棧
DEC BP ;逆序存放轉(zhuǎn)化后的字符,便于主程序調(diào)用SHOW_STR
JMP S
BACK:POP AX ;為了得到正確的IP值,需要出棧一次
RET
DTOC ENDP
;子程序定義開(kāi)始,功能是分離被除數(shù)的各個(gè)位的數(shù)字
;公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N
DIVDW PROC
PUSH AX ;低16位入棧
MOV AX,DX ;將高16位寫(xiě)入AX,
MOV DX,0 ;將高16位置零
DIV CX ;將新的數(shù)除10,
MOV BX,AX ;將商int(H/N)轉(zhuǎn)移到BX,默認(rèn)余數(shù)rem(H/N)在DX
POP AX ;將低16位出棧,
DIV CX ;將[rem(H/N)*65536+L]除10,默認(rèn)余數(shù)在DX
MOV CX,DX ;將余數(shù)轉(zhuǎn)移到CX
MOV DX,BX ;將商int(H/N)轉(zhuǎn)移到dx,相當(dāng)于int(H/N)*65536
RET ;子程序定義結(jié)束
DIVDW ENDP
//C語(yǔ)言中沒(méi)有這兩段,全部隱藏在一句簡(jiǎn)單的printf("%d ", a[i]);之中//
;實(shí)現(xiàn)字符串的輸出
SHOW_STR PROC
S2:MOV AH,2 ;輸出數(shù)字轉(zhuǎn)化后的字符串
MOV DL,DS:[BP]
INT 21H
INC BP ;順序輸出
DEC DI ;數(shù)字的位數(shù)減一
JZ OK ;字符串輸出完了就結(jié)束
JMP S2 ;否則繼續(xù)輸出
OK:MOV AH,2 ;輸出空格
MOV DL,0
INT 21H
RET
SHOW_STR ENDP
//C語(yǔ)言中也沒(méi)有這段,同樣全部隱藏在一句簡(jiǎn)單的printf("%d ", a[i]);之中//
CODES?ENDS
END?START
由以上對(duì)比可以看到,匯編語(yǔ)言中的數(shù)字、字符、變量等的地址分配細(xì)節(jié),都被高級(jí)語(yǔ)言隱藏了,這個(gè)過(guò)程其實(shí)也是一個(gè)程序的編譯過(guò)程;同樣數(shù)字到字符的轉(zhuǎn)換過(guò)程也被隱藏了。所以,用高級(jí)語(yǔ)言編寫(xiě)同一個(gè)程序,就比用匯編語(yǔ)言要簡(jiǎn)單得多。