8086汇编实现冒泡排序、直接插入排序、折半查找
汇编冒泡法排序
汇编实验报告实验题目:从键盘输入任意5个2位有符号十进制数,采用“冒泡法”进行升序排序,输出排序后的结果,并输出排序次数。
实验设计:实验要求用16位机的汇编语言完成,键盘上输入的的数据最终都会以ASCII码形式接受,输出也要求用ASCII码,因而我决定设计专门负责输入和输出的两个子程序。
但是由于要求输入的是有符号的而且是长度不一定不确定的十进制数,用一个子程序直接在输入时转换成二进制会比较麻烦,因而决定可以先以字符串的形式接受来自用户的数据,这样可以以最自由的形式接受数据,不仅数据长度问题可以解决,带不带‘+’‘-’符号也可以识别,而且方便查错。
排序的主要部分是比较简单的,学C的时候已经了解,况且数据结构课又重复了一遍,因而本次实验主要需要解决的还是输入输出、以及数据的转化问题。
我的程序结构比较简单,主要包含几个子程序:GET : 调用10号模块接收一串字符,放进缓存dataEXDTB:解析缓存中的符号数据,转化为二进制并存入数组ansEXBTD:对从BX传过来的二进制数解析,并在屏幕上输出相应的十进制数,无运算结果程序:DATAS SEGMENTDATA DB 21 DUP('$')ANS DW 10 DUP(0)TES DB 'RUN HRER','$'LEN DW 0TMP DW 0SIG DW 00HSTA DW 00H ;STA ANS[STA] IS DIGENT DB 0DH,0AH,'$'RNM DB 'READ 5 DIGITALS',0AH,0DH,'$'PRIT DB 'PAIXU:',0AH,0DH,'$'FINSH DB 'NEW ORDER:','$'EORR DB 'INPUT ERROR!',0AH,0DH,'$'CISHU DB 'EXCHANGE TIME:',0DH,0AH,'$'CIS DW 0EXIT DB 'ENTER A NUMBER TO EXIT',0AH,0DH,'$'DATAS ENDSSTACK SEGMENTTOPE DW 300H DUP(0)STACK ENDSCODES SEGMENTASSUME CS:CODES, DS:DATAS,SS:STACKSTART: ;先跳过写在开头的子程序MOV AX,DATASMOV DS,AXMOV AX,STACKMOV SS,AXMOV SP,00HJMP SART ;AH=09 OUPUT AH=10 INPUT,前面注意有两个字节没用从ds:dx+2开始才是 ;第一个是输入及字符数ENTE PROC ;ENTE DISPLAY '/N' ON THE SCREENPUSH AXPUSH DXMOV AX,OFFSET ENTMOV DX,AXMOV AH,09HINT 21HPOP DXPOP AXRETENTE ENDPGET PROC ;PROC GET READ A TWO BIT DIGITAL FROM USCERPUSH AX ;;DX HAS ADDRESSPUSH DXMOV DX,OFFSET DATAMOV AH,0AH ;GET A LINE OF NUMBERINT 21H;CALL ENTEPOP DXPOP AXRETGET ENDPEXDTB PROC ;PROC EXCHANGE SIGNED DIGITAL TO BINARYPUSH AXPUSH BXPUSH CXPUSH DX ;USE DX TO STORE ANS;ANS[STA] HAS RESULT XOR DX,DXXOR CX,CXMOV BX,OFFSET DATAINC BX ;DS:DX+1 IS THE NUMBER OF INPUTED CHAR MOV CL,[BX] ;cl HAS LENGTHXOR CH,CHINC BX ;NOW BX COME TO FIRST CHAR INPUTEDMOV AL,[BX]CMP AL,'-' ;TO CHECK IF IT IS SIGNJNZ POST ;WITHOUT '-',THAT WILL BE POSTIVEMOV WORD PTR[SIG], 0001H ;SET SIG 0001H IF NEGETIVE JMP SIGNEDPOST:MOV SIG,WORD PTR 0000H ;SET POSTIVECMP AL,'+' ;IF IT HAS '+',IGNORE ITJNE PASSSIGNED:INC BXSUB CX,01HJMP STLOP ;PASS THE SIGN + -PASS: ;DIRECTLY TO NUMBERSCMP AL,'0' ;IF IT IS NUMBERJL NOTHINGCMP AL,'9'JG NOTHINGMOV DL,ALSUB DL,'0'CMP CL,1JE POSTYSUB CX,01HSTLOP:MAINLOOP:MOV AL,[BX]SUB AL,'0'JS NOTHING ;JUMP IF AL-'0'< 0 , ILLEAGLE INPUT CMP AL,09H ;JUMP IF AL-'9'> 0 ,JG NOTHINGMOV DH,DL ;SHIFT DL TO TIMES 10SHL DH,01H ;SHIFT 2 TIMES 4SHL DH,01H ;DL=DL*4+DL=5*DLADD DL,DHSHL DL,01H ;DL=5*DL*2=10*DLADD DL,ALINC BXLOOP MAINLOOPTEST SIG,0001HJZ POSTY ;JUMP TO AVOID -DXNEG DLPOSTY:MOV BX,OFFSET ANSADD BX,STAMOV AL,DLCBWMOV [BX],AXJMP DONENOTHING: ;IF NOT NUMBER , RETURN 0MOV DX,OFFSET EORRMOV AH,09HINT 21HMOV BX,OFFSET ANSADD BX,STAMOV [BX],WORD PTR 0001HDONE:CALL ENTEPOP CXPOP BXPOP AXRETEXDTB ENDPEXBTD PROC ;PROC EXCHANGE BINARY NUMBER IN BX TO DIGITAL PUSH AXPUSH BXPUSH CXPUSH DXCALL ENTE ;DISPLAY '/N'TEST BX,8000HJZ POSTVMOV DL,'-'MOV AH,02HINT 21HNEG BX ;EXCHANGE TO POSTIVEPOSTV:MOV CX,1111HPUSH CXMOV AX,BXCWDMOV BX,10MLOOP:DIV BX ;DIV 10PUSH DX ;PUSH BX MOD 10CWDADD AX,00HJNZ MLOOPDSLOOP: ;DISPLAY NUMPOP DXCMP DX,1111HJE FINISHADD DL,'0'MOV AH,02HINT 21HJMP DSLOOPFINISH:;CALL ENTEPOP DXPOP CXPOP BXPOP AXRETEXBTD ENDPSART:MOV DX,OFFSET PRITMOV AH,09HINT 21HMOV DX,OFFSET RNMMOV AH,09INT 21HMOV CX,05HMOV WORD PTR[STA],0000HGETLOOP:CALL GET ;读入符号数CALL EXDTB ;转为二进制ADD WORD PTR[STA],0002H;存入数组ans LOOP GETLOOPMOV WORD PTR[CIS],00HARRAGE: ;排序MOV CX,05HSUB CX,0001HMOV BX,OFFSET ANSADD BX,CXADD BX,CXLOOP1:MOV TMP,CXPUSH BXLOOP2:MOV AX,WORD PTR[BX]SUB BX,0002HMOV DX,WORD PTR[BX]CMP AX,DXJNS BIGGERINC WORD PTR[CIS]MOV WORD PTR[BX],AXMOV 02H[BX],DXBIGGER:SUB WORD PTR[TMP],0001H JNZ LOOP2POP BXLOOP LOOP1WRITE: ;输出排好序的数MOV DX,OFFSET FINSHMOV AH,09HINT 21HMOV CX,05MOV WORD PTR[STA],0000HMOV BX,OFFSET ANSLOOPWR:PUSH BXADD BX,STAMOV DX,[BX]MOV BX,DXCALL EXBTDPOP BXADD WORD PTR[STA],0002HLOOP LOOPWRCALL ENTEMOV DX,OFFSET CISHUMOV AH,09HINT 21HMOV BX,[CIS]CALL EXBTDCALL ENTEMOV DX,OFFSET EXITMOV AH,09HINT 21HCALL GETMOV AX,4C00HINT 21HCODES ENDSEND START问题及调试:主要问题是数据的转化,当我们用C写程序时,直接可以用%开头的格式命令进行特定类型的数据输入输出,但是用汇编时就没有那么好办了,输入的时候要识别数据,输出也要转化数据。
汇编语言冒泡排序
汇编语⾔冒泡排序终于可以看懂很简单很简单的汇编语⾔代码了,很有成就感^^下⾯是⼀冒泡排序的汇编语⾔代码。
先对代码简要说明⼀下:像“NEXT0:”,以字符串加冒号构成的是⼀个标签,翻译成汇编指令时会⽤偏移地址替代。
原数据放在SOURCE代表的内存单元中,排序后的数据放在RESULT代表的内容单元中。
在冒泡算法中,有两层循环,其中,寄存器BX控制外层循环,CX控制内层循环。
N EQU 4STAC SEGMENT STACKDB 128 DUP (?)STAC ENDSDATA SEGMENTSOURCE DW 7003h,7002h,7008h,7001hRESULT DW N DUP(0)DATA ENDSCODE SEGMENTASSUME CS:CODE, DS:DATA, SS:STACSTART PROC FARPUSH DSXOR AX,AXPUSH AXMOV AX,DATAMOV DS,AXLEA SI,SOURCELEA DI,RESULTMOV CX,NNEXT0: MOV AX,[SI]MOV [DI],AXADD SI,2ADD DI,2LOOP NEXT0CLDMOV BX,N-1MAL1: LEA SI,RESULTMOV CX,BXNEXT: LODSWCMP [SI],AXJAE CONTXCHG [SI],AXMOV [SI-2],AXCONT: LOOP NEXTDEC BXJNZ MAL1RETSTART ENDPCODE ENDSEND START这段代码经过link后⽣成的汇编指令如下:14C1:0000 1E PUSH DS14C1:0001 33C0 XOR AX,AX14C1:000350 PUSH AX14C1:0004 B8C014 MOV AX,14C014C1:0007 8ED8 MOV DS,AX14C1:0009 8D360000 LEA SI,[0000]14C1:000D 8D3E0800 LEA DI,[0008]14C1:0011 B90400 MOV CX,000414C1:0014 8B04 MOV AX,[SI]14C1:00168905 MOV [DI],AX14C1:0018 83C602 ADD SI,+0214C1:001B 83C702 ADD DI,+0214C1:001E E2F4 LOOP 001414C1:0020 FC CLD14C1:0021 BB0300 MOV BX,000314C1:0024 8D360800 LEA SI,[0008]14C1:0028 8BCB MOV CX,BX14C1:002A AD LODSW14C1:002B 3904 CMP [SI],AX14C1:002D 7305 JNB 003414C1:002F 8704 XCHG AX,[SI]14C1:0031 8944FE MOV [SI-02],AX 14C1:0034 E2F4 LOOP 002A14C1:0036 4B DEC BX14C1:0037 75EB JNZ 002414C1:0039 CB RETF14C1:003A 0000 ADD [BX+SI],AL 14C1:003C 0000 ADD [BX+SI],AL 14C1:003E 0000 ADD [BX+SI],AL。
汇编语言实现冒泡排序(一)
;用汇编语言实现实现冒泡排序,并将排序后的数输出DATAS SEGMENTA dw 100,344,3435,43433,3438,343,134,80,8,1000,65535,54,45N=$-A ;计算数字所占的字节数DATAS ENDSCODES SEGMENTASSUME CS:CODES,DS:DATASSTART:MOV AX,DATASMOV DS,AXMOV SI,0 ;SI遍历数字;前一个数的地址MOV CX,N/2-1 ;设置循环次数,M(M=N/2)个数需要,循环M-1次 CALL BUBBLE ;调用BUBBLE将原来的数排序;输出排序后的数MOV CX,N/2 ;循环M次输出排序后的M个数MOV SI,0 ;SI遍历排序后的数MOV DI,0 ;用DI记录数字的位数MOV BP,N+5 ;BP用于遍历存储的转化后的字符的位置SHOW: PUSH CX ;循环次数入栈MOV DX,0 ;由于将要进行16位除需要置高16位为0MOV AX,[SI] ;低16位为排序后的数CALL DTOC ;调用DTOC将十进制数转换为字符串CALL SHOW_STR ;调用SHOW_STR将一个数转化得到的字符串输出ADD SI,2 ;下一个数POP CX ;循环次数出栈栈LOOP SHOWMOV AH,4CHINT 21H;冒泡排序BUBBLE PROCL1: PUSH CX ;将循环次数入栈LEA SI,A ;SI遍历DATAS数据段的数字L2: MOV AX,A[SI] ;将前一个数存于AXCMP AX,A[SI+2] ;比较前后两个数JBE NEXT ;如果前一个数小于或等于后一个数则继续本轮的比较XCHG AX,A[SI+2] ;否则,交换前后两个数的位置MOV A[SI],AXNEXT:ADD SI,2 ;下一个数LOOP L2 ;注意内层循环的次数已经确定了POP CX ;将循环次数出栈LOOP L1 ;下一轮比较RETBUBBLE ENDP;将十进制数转换为字符串并储存起来DTOC PROCS:MOV CX,10 ;将除数10,放入CX中CALL DIVDW ;调用DIVDW程序ADD CL,30H ;把数字转换为ASCII码,这样就能显示了MOV DS:[BP],CL ;把ASCII码放到内存中INC DI ;用DI记录循环的次数PUSH AX ;将低16位入栈ADD AX,DX ;将高位与低位相加,接着判断是否已经除尽JZ BACK ;除尽后返回调用处POP AX ;将低16位出栈DEC BP ;逆序存放转化后的字符,便于主程序调用SHOW_STR JMP SBACK:POP AX ;为了得到正确的IP值,需要出栈一次RETDTOC ENDP;子程序定义开始,功能是分离被除数的各个位的数字;公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/NDIVDW PROCPUSH AX ;低16位入栈MOV AX,DX ;将高16位写入AX,MOV DX,0 ;将高16位置零DIV CX ;将新的数除10,MOV BX,AX ;将商int(H/N)转移到BX,默认余数rem(H/N)在DX POP AX ;将低16位出栈,DIV CX ;将[rem(H/N)*65536+L]除10,默认余数在DXMOV CX,DX ;将余数转移到CXMOV DX,BX ;将商int(H/N)转移到dx,相当于int(H/N)*65536RET ;子程序定义结束DIVDW ENDP;实现字符串的输出SHOW_STR PROCS2:MOV AH,2 ;输出数字转化后的字符串MOV DL,DS:[BP]INT 21HINC BP ;顺序输出DEC DI ;数字的位数减一JZ OK ;字符串输出完了就结束JMP S2 ;否则继续输出OK:MOV AH,2 ;输出空格MOV DL,0INT 21HRETSHOW_STR ENDPCODES ENDSEND START;实现冒泡排序,并将排序后的数输出DATAS SEGMENTA dw 100,344,3435,43433,3438,343,134,80,8,1000,65535,54,45N=$-A ;计算数字所占的字节数DATAS ENDSCODES SEGMENTASSUME CS:CODES,DS:DATASSTART:MOV AX,DATASMOV DS,AXMOV SI,0 ;SI遍历数字;前一个数的地址MOV CX,N/2-1 ;设置循环次数,M(M=N/2)个数需要,循环M-1次 CALL BUBBLE ;调用BUBBLE将原来的数排序;输出排序后的数MOV CX,N/2 ;循环M次输出排序后的M个数MOV SI,0 ;SI遍历排序后的数MOV DI,0 ;用DI记录数字的位数MOV BP,N+5 ;用于遍历存储的转化后的字符的位置SHOW: PUSH CX ;循环次数入栈MOV DX,0 ;由于将要进行16位除需要置高16位为0MOV AX,[SI] ;低16位为排序后的数CALL DTOC ;调用DTOC将十进制数转换为字符串CALL SHOW_STR ;调用SHOW_STR将一个数转化得到的字符串输出ADD SI,2 ;下一个数POP CX ;循环次数出栈栈LOOP SHOWMOV AH,4CHINT 21HBUBBLE PROCL1: PUSH CX ;将循环次数入栈LEA SI,A ;SI遍历DATAS数据段的数字L2: MOV AX,A[SI] ;将前一个数存于AXCMP AX,A[SI+2] ;比较前后两个数JBE NEXT ;如果前一个数小于或等于后一个数则继续本轮的比较XCHG AX,A[SI+2] ;否则,交换前后两个数的位置MOV A[SI],AXNEXT:ADD SI,2 ;下一个数LOOP L2 ;注意内层循环的次数已经确定了POP CX ;将循环次数出栈LOOP L1 ;下一轮比较RETBUBBLE ENDP;将十进制数转换为字符串并储存起来DTOC PROCS:MOV CX,10 ;将除数10,放入CX中CALL DIVDW ;调用DIVDW程序ADD CL,30H ;把数字转换为ASCII码,这样就能显示了MOV DS:[BP],CL ;把ASCII码放到内存中INC DI ;用DI记录循环的次数PUSH AX ;将低16位入栈ADD AX,DX ;将高位与低位相加,接着判断是否已经除尽JZ BACK ;除尽后返回调用处POP AX ;将低16位出栈DEC BP ;逆序存放转化后的字符,便于主程序调用SHOW_STR JMP SBACK:POP AX ;为了得到正确的IP值,需要出栈一次RETDTOC ENDP;子程序定义开始,功能是分离被除数的各个位的数字;公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/NDIVDW PROCPUSH AX ;低16位入栈MOV AX,DX ;将高16位写入AX,MOV DX,0 ;将高16位置零DIV CX ;将新的数除10,MOV BX,AX ;将商int(H/N)转移到BX,默认余数rem(H/N)在DX POP AX ;将低16位出栈,DIV CX ;将[rem(H/N)*65536+L]除10,默认余数在DXMOV CX,DX ;将余数转移到CXMOV DX,BX ;将商int(H/N)转移到dx,相当于int(H/N)*65536 RET ;子程序定义结束DIVDW ENDP;实现字符串的输出SHOW_STR PROCS2:MOV AH,2 ;输出数字转化后的字符串MOV DL,DS:[BP]INT 21HINC BP ;顺序输出DEC DI ;数字的位数减一JZ OK ;字符串输出完了就结束JMP S2 ;否则继续输出OK:MOV AH,2 ;输出空格MOV DL,0INT 21HRETSHOW_STR ENDPCODES ENDSEND START。
查找和排序(折半查找、二叉插入查找、直接插入排序、折半排序、快速排序、选择排序、堆排序、归并排序)
int key;
cin>>key;
cout<<"折半查找:"<<endl;
Search_Bin(st,key);
cout<<"二叉排序查找"<<endl;
BiTree T=NULL;
for(i=0;i<st.length;i++)
SearchandIn(T,st.elem[i]);
{
MSort(L,L,1,L.length-1);
{
for(int i=1;i<L.length;i++)
cout<<L.r[i].key<<" ";
cout<<endl;
}
void main()
{
SSTable st;
--high;
int temp=L.r[low].key;
L.r[low].key=L.r[high].key;
L.r[high].key=temp;
while(low<high&&L.r[low].key<=pivotkey)
++low;
temp=L.r[low].key;
return false;
}
if(key==T->data)
return true;
else if(key<T->data)
return SearchandIn(T->lchild,key);
基于8086用汇编语言实现的十个有符号数的排序(冒泡排序算法,输入为补码,从小到大)
提示:在做实验时,我们要自己将代码区和数据区分开,因为8086上没有软件帮我们完成这个任务。
MOV R0,#218 //之所以选择208这个大点的地址,是因为避免将数据写到了代码区LOOP1:IN //将数据读入AADD A,#128 //将补码转换为其对应的移码,因为补码本身参与加减不能比较出大//小,而移码就是将其真值在数轴上平移了2的n次方MOV @R0,AMOV A,R0sub a,#1SUB A,#208 //判断有没有输入完10个数JZ LOOP2 //输入完数据,跳转ADD A,#208MOV R0,AJMP LOOP1//没有输入完,就跳回接着输入LOOP2:MOV R0,#9 //9轮循环比较就可以排完序MOV R1,#209MOV R2,#210LOOP4:MOV A,@R2SUBC A,@R1JC LOOP3 //若210地址指向的单元中的数比209地址指向的单元中的小,则交//换LOOP5:MOV A,R2ADD A,#1SUBC A,#219 //判断此轮有没有比较完JZ LOOP6 //若比较完,就跳到LOOP6,否则继续比较ADD A,#219MOV R2,AJMP LOOP4LOOP3:MOV A,@R1MOV 208,AMOV A,@R2MOV @R1,AMOV A,208MOV @R2,AJMP LOOP5 //交换完了就跳回LOOP6: MOV A,R1ADD A,#1MOV R1,AADD A,#1MOV R2,A //让R2始终指向的是R1下一个单元MOV A,R0SUB A,#1JZ LOOP7 //判断9轮比较有没有完成,若完成,跳LOOP7,否则,继续比//较MOV R0,AJMP LOOP4LOOP7: MOV R0,#218LOOP9: MOV A,@R0 //下面这一段代码就是将数还原,因为原来我们是那人家的移码//形式来比较的,相信下面这一段就不用多讲了吧ADD A,#128MOV @R0,AMOV A,R0sub a,#1SUB A,#208JZ LOOP8ADD A,#208MOV R0,AJMP LOOP9LOOP8:END。
排序算法:折半插入排序
排序算法:折半插⼊排序算法分析:(1)时间复杂度 从时间上⽐较,折半查找⽐顺序查找快,所以就平均性能来说,折半插⼊排序优于直接插⼊排序。
折半插⼊排序所需要的关键字⽐较次数与待排序序列的初始排列⽆关,仅依赖于记录的个数。
不论初始序列情况如何,在插⼊第i个记录时,需要经过logi+1(向下取整+1)次⽐较,才能确定它插⼊的位置。
所以当记录的初始排列为正序或接近正序时,直接插⼊排序⽐折半插⼊排序执⾏的关键字⽐较次数要少。
折半插⼊排序的对象移动次数与直接插⼊排序相同,依赖于对象的初始排列。
在平均情况下,折半插⼊排序仅减少了关键字的⽐较次数,⽽记录的移动次数不变。
因此,折半插⼊排序的时间复杂度仍然为O(n^2)。
(2)空间复杂度 折半插⼊排序所需附加存储空间和直接插⼊排序相同,只需要⼀个记录的辅助空间r[0],所以空间复杂度为O(1)算法特点:(1)是稳定排序。
(2)因为要进⾏折半插⼊查找,所以只能⽤于顺序结构,不能⽤于链式结构。
(3)适合初始记录⽆序、n较⼤的情况。
#include<iostream>#include<vector>using namespace std;void BSort(int a[],int n){for (int i = 1; i < n; i++)//数组中的第⼀个元素最为已经排好的序列,所以从数组的第⼆个元素开始排{int key = a[i];//带插⼊元素int low = 0, high = i - 1;while (low <= high){int mid = (low + high) / 2;if (key < a[mid]){high = mid - 1;}else{low = mid + 1;}}for (int j = i - 1; j >= high + 1; j--){//i-1是已经排好序的序列的数量,high+1是待插⼊的的位置,元素后移腾出high+1这个位置a[j + 1] = a[j];}a[high + 1] = key;}}int main(){int a [11] = { 2,6,4,5,54,53,53,5,34,34,32};BSort(a, 11);for (int i = 0; i < 11; i++){cout << a[i] << " ";}return 0;}。
用Java实现常见的8种内部排序算法
⽤Java实现常见的8种内部排序算法⼀、插⼊类排序插⼊类排序就是在⼀个有序的序列中,插⼊⼀个新的关键字。
从⽽达到新的有序序列。
插⼊排序⼀般有直接插⼊排序、折半插⼊排序和希尔排序。
1. 插⼊排序1.1 直接插⼊排序/*** 直接⽐较,将⼤元素向后移来移动数组*/public static void InsertSort(int[] A) {for(int i = 1; i < A.length; i++) {int temp = A[i]; //temp ⽤于存储元素,防⽌后⾯移动数组被前⼀个元素覆盖int j;for(j = i; j > 0 && temp < A[j-1]; j--) { //如果 temp ⽐前⼀个元素⼩,则移动数组A[j] = A[j-1];}A[j] = temp; //如果 temp ⽐前⼀个元素⼤,遍历下⼀个元素}}/*** 这⾥是通过类似于冒泡交换的⽅式来找到插⼊元素的最佳位置。
⽽传统的是直接⽐较,移动数组元素并最后找到合适的位置*/public static void InsertSort2(int[] A) { //A[] 是给定的待排数组for(int i = 0; i < A.length - 1; i++) { //遍历数组for(int j = i + 1; j > 0; j--) { //在有序的序列中插⼊新的关键字if(A[j] < A[j-1]) { //这⾥直接使⽤交换来移动元素int temp = A[j];A[j] = A[j-1];A[j-1] = temp;}}}}/*** 时间复杂度:两个 for 循环 O(n^2)* 空间复杂度:占⽤⼀个数组⼤⼩,属于常量,所以是 O(1)*/1.2 折半插⼊排序/** 从直接插⼊排序的主要流程是:1.遍历数组确定新关键字 2.在有序序列中寻找插⼊关键字的位置* 考虑到数组线性表的特性,采⽤⼆分法可以快速寻找到插⼊关键字的位置,提⾼整体排序时间*/public static void BInsertSort(int[] A) {for(int i = 1; i < A.length; i++) {int temp = A[i];//⼆分法查找int low = 0;int high = i - 1;int mid;while(low <= high) {mid = (high + low)/2;if (A[mid] > temp) {high = mid - 1;} else {low = mid + 1;}}//向后移动插⼊关键字位置后的元素for(int j = i - 1; j >= high + 1; j--) {A[j + 1] = A[j];}//将元素插⼊到寻找到的位置A[high + 1] = temp;}}2. 希尔排序希尔排序⼜称缩⼩增量排序,其本质还是插⼊排序,只不过是将待排序列按某种规则分成⼏个⼦序列,然后如同前⾯的插⼊排序⼀般对这些⼦序列进⾏排序。
顺序查找直接查找折半查找算法
顺序查找直接查找折半查找算法一、顺序查找算法顺序查找也被称为线性查找,是一种简单直观的算法。
其基本原理是逐个遍历数据集中的元素,直到找到目标值为止。
算法步骤如下:1.从数据集的第一个元素开始顺序遍历。
2.如果当前元素与目标值相同,返回元素的索引。
3.如果遍历到数据集的最后一个元素仍未找到目标值,返回失败。
顺序查找算法的时间复杂度为O(n),其中n为数据集的大小。
由于需要遍历整个数据集,这种算法适用于小型数据集。
二、直接查找算法直接查找算法也被称为线性查找优化算法,其思想是在遍历数据集时,通过跳跃一定步长快速确定目标值所在的范围,然后在该范围内进行顺序查找。
算法步骤如下:1.设定步长为k。
2.从数据集的第一个元素开始,每次跳跃k个元素。
3.如果当前元素大于目标值,将步长减半并继续跳跃,直到找到目标值或步长变为1为止。
4.在跳跃范围内进行顺序查找,找到目标值则返回索引,否则返回失败。
直接查找算法的时间复杂度为O(n/k),其中n为数据集的大小,k为步长。
通过调整步长,可以在时间和空间之间取得平衡。
折半查找算法是一种效率较高的算法,也被称为二分查找。
其基本原理是将数据集分为两半,通过比较目标值与中间元素的大小关系来确定目标值所在的范围,然后在该范围内进行递归查找。
算法步骤如下:1.将数据集按升序或降序排列。
2.初始化左右指针,分别指向数据集的第一个和最后一个元素。
3.计算中间元素的索引。
4.如果中间元素等于目标值,则返回索引。
5.如果中间元素大于目标值,则更新右指针为中间元素的前一个元素,重复步骤36.如果中间元素小于目标值,则更新左指针为中间元素的后一个元素,重复步骤37.当左指针大于右指针时,返回失败。
折半查找算法的时间复杂度为O(logn),其中n为数据集的大小。
由于每次都将数据集分为两半,因此效率较高。
但是该算法要求数据集必须有序。
综上所述,顺序查找、直接查找和折半查找算法都是常用的算法,适用于不同规模和有序性的数据集。
折半插入排序
折半插入排序
折半插入排序法,又称四舍五入排序法。
是按照折半法和插入法交替进行逐步排除错误的一种方法,也叫“舍弃小的,保留大的”或“用全排出去,用缺补上来”排序法.它适合于成对象形的数据,也就是说要求将某些对象先看作一组,然后再把它们每一对当作两个来排列,这样容易产生正确的结果。
常见的排序问题,通常包含多对对象,而且要求所选择的对象都必须有相同的特征值。
由于相邻的两个单元可能互为相反数,故在实际操作过程中往往需要将两者按互为倒数来处理,这就引申出一系列简便计算,即求整数部分的个位数字,因此排序也是很容易解决的。
下面举例说明其思路和方法。
例如有10名学生参加考试,前8人平均成绩为80分,最后2人平均成绩为90分,则求出平均成绩为81分的2人平均成绩的值。
应用该方法时要注意以下几点:1、运算符号、公式及各种运算之间不能混淆;2、在用这种方法时还需进一步分析原来顺序中有无矛盾,是否具备等价性(平均成绩相等),排除非同质的现象(比如全为80分,或全为90分);3、用该方法解决的问题,只要求得到最终结果,不要求知道开始时的情况,但要求知道结束时的情况。
在用这种方法时还需进一步分析原来顺序中有无矛盾,是否具备等价性(平均成绩相等),排除非同质的现象(比如全为80分,或全为90分)。
3、使用了这种方法后,若遇到不能直接利用上述方法解决的问
题,可采取折半插入排序法。
例如,已知某班男女生人数分别为20人和21人,求男生人数占总人数的百分比。
4、用该方法解决的问题,只要求得到最终结果,不要求知道开始时的情况,但要求知道结束时的情况。
8086汇编实现冒泡排序、直接插入排序、折半查找
(2)直接插入法 直接插入排序:将一个数据插入到一个已排好序的数据中,主要步骤如下:
① 查找应该插入的位置,这个过程免不了要比较数据的大小; ② 找到位置后,需将这个位置以及其后的数据都向后移动一位,空出此位置,等待插入 ③ 插入数据。
其 C 语言版的代码如下:
for(int i=2;i<=100;i++)
DSEG SEGMENT SCORE DB 31H,02H,15H,4H,5H,6H,7H,8H,9H,10H,90 DUP(05H) MAX DB ? MIN DB ?
DSEG ENDS CSEG SEGMENT
ASSUME DS:DSEG,CS:CSEG START: MOV AX,DSEG
MOV DS,AX
;相当于 i
L2: MOV AL,[BX+DI] ; L2 为内循环,(DI)为循环变量,相当于 j
CMP AH,AL
JAE L3
MOV DH,AH
;AH<Al,交换两个数
MOV AH,AL
MOV AL,DH
MOV [BX+DI],AL ;将交换后的数存入存储器
MOV [BX+SI],AH ;这两步很重要
L4: MOV DL,[BX+DI] ;从内存中取出 a[j],给(DL)
CMP DH,DL
;比较 a[0]和 a[j]
JAE L5
;a[0]<a[j],向后移
MOV [BX+DI+1],DL ;存入内存,实现真正的后移
DEC DI
;j--
JMP L4
L5: MOV [BX+DI+1],DH ;a[0]>=a[j],a[0]—>a[j+1],实现直接插入
汇编语言汇编语言实现ifwhilefor以及编写冒泡排序
汇编语言汇编语言实现ifwhilefor以及编写冒泡排序在计算机科学中,汇编语言是一种底层编程语言,它直接与计算机的硬件交互。
在汇编语言中,我们可以利用条件语句(if)、循环语句(while、for)以及排序算法(冒泡排序)来实现各种功能。
本文将介绍汇编语言中如何使用这些关键字来编写相应功能的代码,并且以冒泡排序算法为例进行详细说明。
一、if语句实现if语句在汇编语言中通常使用条件判断指令来实现。
下面是一个示例代码,演示如何使用if语句判断两个数的大小关系:```section .datanum1 db 10num2 db 20result db 0section .textglobal _start_start:mov al, byte[num1]mov bl, byte[num2]cmp al, bl ; 比较num1和num2的值jg greater ; 如果num1 > num2,则跳转到greater标签处jl less ; 如果num1 < num2,则跳转到less标签处jmp equal ; 如果num1 = num2,则跳转到equal标签处greater:mov byte[result], 1jmp doneless:mov byte[result], -1jmp doneequal:mov byte[result], 0jmp donedone:; 其他操作,比如打印结果或进行下一步操作```在上述代码中,我们将两个数分别存在`num1`和`num2`变量中,用`cmp`指令进行比较,根据比较结果使用`jmp`指令跳转到相应的标签位置。
通过这样的比较和跳转操作,我们可以实现基本的if语句功能。
二、while语句实现while语句在汇编语言中可以通过使用条件循环指令来实现。
下面是一个示例代码,演示如何使用while语句计算1到10的和:```section .datasum dw 0counter dw 1section .textglobal _start_start:mov cx, 10 ; 设置循环次数mov ax, 1 ; 设置计数器初始值loop_start:add word[sum], ax ; 将计数器的值加到sum中inc ax ; 计数器自增1loop loop_start ; 循环开始; 其他操作,比如打印结果或进行下一步操作```在上述代码中,我们将循环次数存储在`cx`寄存器中,将计数器的初始值存储在`ax`寄存器中。
折半查找法算法
折半查找法算法
折半查找法是一种在有序数组中查找某一特定元素的搜索算法。
它的基本思想是:首先,将数组的中间位置的元素与要查找的元素进行比较,如果相等,则查找成功;如果比要查找的元素大,则在数组的前半部分继续查找;如果比要查找的元素小,则在数组的后半部分继续查找。
这种方法可以大大减少查找的次数,提高查找的效率。
折半查找法的步骤如下:
1. 首先,从有序数组的中间位置开始查找,将中间位置处的元素与要查找的元素进行比较。
2. 如果相等,则查找成功;
3. 如果比要查找的元素大,则在数组的前半部分继续查找;
4. 如果比要查找的元素小,则在数组的后半部分继续查找;
5. 重复上述步骤,直到找到要查找的元素,或者查找范围为空。
折半查找法的时间复杂度为O(log2n),其中n为数组的长度。
它的优点是查找速度快,比
顺序查找要快得多,而且它只需要对数组进行一次排序,就可以多次使用。
但是,它的缺点是只能用于有序数组,如果数组无序,则必须先进行排序,才能使用折半查找法。
总之,折半查找法是一种高效的查找算法,它可以大大减少查找的次数,提高查找的效率。
但是,它只能用于有序数组,如果数组无序,则必须先进行排序,才能使用折半查找法。
汇编实现冒泡排序的方法示例
汇编实现冒泡排序的⽅法⽰例冒泡排序算法的运作如下:(从后往前)1.⽐较相邻的元素。
如果第⼀个⽐第⼆个⼤,就交换他们两个。
2.对每⼀对相邻元素作同样的⼯作,从开始第⼀对到结尾的最后⼀对。
在这⼀点,最后的元素应该会是最⼤的数。
3.针对所有的元素重复以上的步骤,除了最后⼀个。
4.持续每次对越来越少的元素重复上⾯的步骤,直到没有任何⼀对数字需要⽐较。
以下为实现代码:S0 SEGMENT STACKDW 30 DUP(?)TOP LABEL WORDS0 ENDSS1 SEGMENTTIP DB "Input ten number and separate the numbers with space:", 0DH, 0AH, 24HARY DW 20 DUP(0)CRLF DB 0DH, 0AH, 24HN DW 0S1 ENDSS2 SEGMENTASSUME SS:S0, DS:S1, CS:S2, ES:S1P PROC FARMOV AX, S0MOV SS, AXLEA SP, TOPMOV AX, S1MOV DS, AXMOV AX, S1MOV ES, AXLEA DX, TIPMOV AH, 9INT 21HLEA SI, ARYXOR DX, DXMOV BL, 10MOV CX, 10INPUT: MOV AH, 1INT 21HCMP AL, 20H ;空格分隔字符JE SAVE;输⼊⼗进制数,将数存⼊SI对应的内存单元MOV DL, ALMOV AX, [SI]MUL BLSUB DL, 30HADD AL, DLMOV [SI], AXJMP INPUTSAVE:ADD SI, 2LOOP INPUT;数组保存完毕LEA SI, ARYMOV DI, SIADD DI, 2CMPA: MOV BX, [DI]CMP BX, [DI-2]JA CONMOV DX, [DI-2]PUSH DXMOV [DI-2], BXPOP DXMOV [DI], DXCON: ADD DI, 2DEC CHCMP CH, 0JNE CMPACALL PRINTMOV DI, SIADD DI, 2DEC CLMOV CH, CLCMP CL, 1JNE CMPA;以下为⼗进制输出ARY中的数EXIT: MOV AH, 4CHINT 21HP ENDPPRINT PROC NEARPUSH SIPUSH CXPUSH AXPUSH DXLEA DX, CRLFMOV AH, 9INT 21HLEA SI, ARYMOV CX, 10L1: MOV AX, [SI]MOV N, AXCALL OUTPUTADD SI, 2MOV DX, 20HMOV AH, 2INT 21HLOOP L1POP DXPOP AXPOP CXPOP SIRETPRINT ENDPOUTPUT PROC NEARPUSH AXPUSH BXPUSH CXPUSH DXXOR CX, CXMOV AX, NMOV BX, 10L2: XOR DX, DXDIV BXPUSH DXINC CXL3: POP DXADD DX, 30HMOV AH, 2INT 21HLOOP L3POP DXPOP CXPOP BXPOP AXRETOUTPUT ENDPS2 ENDSEND P以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
详解排序算法(一)之3种插入排序(直接插入、折半插入、希尔)
详解排序算法(⼀)之3种插⼊排序(直接插⼊、折半插⼊、希尔)直接插⼊排序打过牌的⼈都知道,当我们拿到⼀张新牌时,因为之前的牌已经经过排序,因此,我们只需将当前这张牌插⼊到合适的位置即可。
⽽直接插⼊排序,正是秉承这⼀思想,将待插⼊元素与之前元素⼀⼀⽐较,从⽽找到合适的插⼊位置。
那么使⽤直接插⼊排序,具体是怎样操作的呢?我们取 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 来进⾏⽰范。
(1)第1轮排序,3之前⽆可⽐较值,因此我们从44开始操作,取44和3⽐较,⼤于3,顺序保持不变。
得数据3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48(2)第2轮排序,取38和44⽐较,38 < 44,再将38与3⽐较,38 > 3,故将38放于第2位,得数据3, 38, 44, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48(3)第3轮排序,取5与44⽐较,5 < 44,再将5与38⽐较,5 < 38,再将5与3⽐较,5 > 3, 置于第2位,得数据3, 5, 38, 44, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48(4)如此经过14轮排序后,得到最终结果2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50动态图javascript实现function directInsertSort (arr) {let compare, // 对⽐元素下标current // 待插⼊元素值for (let i = 1; i < arr.length; i++) {current = arr[i]compare = i - 1while (current < arr[compare] && compare >= 0) {arr[compare + 1] = arr[compare]compare--}arr[compare + 1] = current}return arr}折半插⼊排序细⼼的同学可能已经注意到,当我们要将⼀个元素插⼊合适的位置时,其之前的元素是有序的,因此,我们可以⽤折半查找的⽅式来⽐对并插⼊元素,也就是所谓的折半插⼊排序。
详解折半插入排序算法
详解折半插⼊排序算法折半插⼊排序算法的时间复杂度:O(nlogn)折半插⼊排序利⽤⼆分法的思想,在⼀个有序的序列中,找到新元素在该序列中的位置,然后插⼊。
如图1所⽰,共有n个元素,前i个元素已经是有序序列,现在要将第i个元素插⼊其中。
折半插⼊排序需要做两步⼯作:找到待插⼊元素的位置、插⼊。
图1 插⼊排序⽰意图⾸先要定义两个指针(不是语法⾥⾯的指针,是下标的意思)low和high⽤于寻找a[i]的插⼊位置,low指向a[0],high指向a[i-1],中点mid=(low+high)/2,图2 “折半”⽰意图如图2所⽰⼆分法的思想是,⽐较a[i]与a[mid]的⼤⼩,若a[i]>a[mid],说明a[i]的位置应该在mid~high之间,将区间[low,high]缩短为[mid+1,high],令指针low=mid+1;若a[i]<=a[mid],说明a[i]的位置应该在low~mid之间,将区间压缩为[low,mid-1],令指针high=mid-1。
每次折半之后,a[i]的位置应该在[low,high]之间。
如此循环,low与high渐渐靠近,直到low>high跳出循环,a[i]的位置找到,low即为a[i]应该放置的位置。
找到a[i]的位置之后进⾏插⼊,先将a[low]~a[i-1]这些元素向后平移⼀个元素的位置,然后将a[i]放到low位置。
⽤Dev-C++编写的C++代码:#include <iostream>using namespace std;void BinSort(int *a,int n) //对int数组进⾏从⼩到⼤的排序{for(int i=1;i<n;i++) //开始以a[0]作为有序序列,从a[1]开始找到当前元素a[i]应该放置的位置{int low=0,high = i-1,mid;//每次寻找a[i]的位置,都要更新这些数据while(low<=high) //⼆分思想循环寻找a[i]的位置{mid = (low+high) / 2;if(a[i]<=a[mid])high = mid - 1; //high指针减⼩elselow = mid + 1; //low指针增加} //循环结束,low就是a[i]应该放置的位置int temp = a[i];for(int j=i;j>low;j--) //将元素向后平移a[j] = a[j-1];a[low] = temp; //将元素temp = a[i] 放置到low位置}}int main() //举例说明{int n = 10;int a[10] = {5,8,9,4,7,5,6,3,1,11};BinSort(a,n);for(int i=0;i<n;i++)cout << a[i] << " ";cout << endl;return 0;}⼀个细节:为什么内层的循环while(low<=high){...}结束之后以low作为a[i]应该放置的位置?观察指针low与high重合之前与之后⼆者位置变化情况。
用汇编语言冒泡排序经典程序
冒泡排序时间复杂度
最好情况:O(n)
平均情况:O(n²)
最坏情况:O(n²)
Part Two
汇编语言基础知识
汇编语言概述
汇编语言是一种低级编程语言,与机器语言相对应。
它使用助记符和操作码表示指令,易于理解和编写。
汇编语言通常用于嵌入式系统、操作系统等底层开发。
注意事项:确保编译和链接的正确性,避免出现错误和警告
工具使用:使用编译器和链接器等工具进行编译和链接
链接过程:将目标文件合并成一个可执行文件
程序运行及结果
输入数据:随机生成一组整数
程序运行过程:按照冒泡排序算法进行排序
输出结果:排序后的整数序列
测试结果:对多个不同规模的输入数据进行测试,验证程序的正确性和稳定性
代码注释:对每行代码进行详细解释,帮助理解算法实现过程
代码解析:分析代码结构,解释冒泡排序算法的汇编语言实现方式
寄存器使用:说明在汇编语言中如何使用寄存器进行数据交换和比较
优化点:分析代码中可以优化的地方,提高程序执行效率
Part Four
程序运行及测试
程序编译链接
编译过程:将源代码转换成机器语言
指令格式:汇编语言指令由操作码和操作数组成,操作码指明指令的操作类型,操作数指明操作数或操作数的地址。
伪指令:伪指令不是真正的计算机指令,而是用于告诉汇编程序如何组织程序的一种指示。常见的伪指令包括ORG、END、DB、DW等。
Part Three
汇编语言实现冒泡排序
排序数据准备
确定排序数据类型:根据具体需求选择合适的数据类型,如整数、字符等。
优化效果:通过减少数据交换次数,可以提高冒泡排序算法的执行效率,减少程序运行时间
汇编语言基础程序 -回复
汇编语言基础程序-回复三种不同的排序算法(冒泡排序,插入排序和选择排序)在汇编语言中的基本实现。
本文将介绍每种排序算法的原理和实现步骤,并通过编写相应的汇编程序进行演示。
冒泡排序(Bubble Sort)是一种简单的排序算法,它的基本思想是通过比较相邻元素的大小,将较大(或较小)的元素逐步交换到右(或左)侧,从而实现排序。
具体而言,冒泡排序从第一个元素开始,一直到倒数第二个元素,依次比较相邻元素的大小,并逐步交换。
这样经过一轮比较和交换后,最大(或最小)的元素会浮动到右(或左)侧。
然后,继续进行下一轮比较和交换,直到所有元素都以正确的顺序排列。
代码实现:assemblysection .dataarray db 5, 9, 1, 3, 2, 8, 4, 7, 6 ; 待排序数组length equ -array ; 数组长度section .textglobal _start_start:mov ecx, 0 ; 循环计数器置0mov edx, length ; 数组长度outer_loop:cmp ecx, edx ; 判断循环是否结束jge end ; 结束循环mov eax, edx ; 内层循环次数sub eax, ecxdec eax ; 循环次数减1inner_loop:mov edi, ecx ; 当前元素索引mov esi, ecx + 1 ; 下一个元素索引mov al, [array + edi] ; 当前元素mov ah, [array + esi] ; 下一个元素cmp al, ah ; 比较大小jle skip_swap ; 如果当前元素小于等于下一个元素,则跳过交换; 交换当前元素和下一个元素mov dl, [array + edi]xchg dl, [array + esi]mov [array + edi], dlskip_swap:inc ecx ; 循环计数器加1cmp ecx, edx ; 判断是否还需进行下一轮比较和交换jl inner_loop ; 如果不需要,则退出内层循环inc edx ; 数组长度减1loop outer_loop ; 继续下一轮比较end:; 排序完成; 输出排序后的数组mov ecx, length ; 循环计数器置为数组长度print_loop:movzx eax, byte [array + ecx - 1] ; 输出当前元素add al, '0'mov [output_char], almov eax, 4mov ebx, 1mov ecx, output_charmov edx, 1int 0x80dec ecx ; 循环计数器减1cmp ecx, 0 ; 判断是否还需输出下一个元素jg print_loop; 退出程序mov eax, 1xor ebx, ebxint 0x80section .bssoutput_char resb 1插入排序(Insertion Sort)是一种简单直观的排序算法,它的基本思想是将一个待排序的元素插入已排序序列中的合适位置,从而逐步完成排序。
8086汇编程序,实现对输入字符进行冒泡排序后输出
STACK1 SEGMENT STACKDW 256 DUP(?)STACK1 ENDSDATA SEGMENT USE16MES1 DB 'Welcome!',0AH,0DH,0AH,0DH,'Please input several alphabets:',0AH,0DH,'Press ENTER to finish!',0AH,0DH,0AH,0DH,'$'MES2 DB 'Number of total input letters(Decimal):','$'MES3 DB 'Number of big letters(Decimal):','$'MES4 DB 'Number of small letters(Decimal):','$'ALPHA DB 100 DUP(0)SUM DW 3 DUP(0)DATA ENDSCRLF MACROMOV DL,0AHMOV AH,02HINT 21HMOV DL,0DHMOV AH,02HINT 21HENDMOUTCHAR MACRO XMOV DL,XMOV AH,02HINT 21HENDMOUTSTR MACRO XLEA DX,X ;提示显示开始MOV AH,09HINT 21H ;提示显示结束ENDMSHOWNUM MACRO XMOV AX,XMOV CL,0AHDIV CLMOV CL,ALMOV CH,AHADD CH,30HADD CL,30HOUTCHAR CLOUTCHAR CHCRLFENDMSHOWRLT MACRO X,Y,Z,KCMP X,0HJE KMOV CX,XMOV BX,YZ: OUTCHAR ALPHA[BX]INC BXLOOP ZK: CRLFCRLFENDMCODE SEGMENT USE16ASSUME CS:CODE,DS:DATA START:MOV AX,DATAMOV DS,AXOUTSTR MES1 ;输出提示语MOV BX,0HAGAIN: MOV AH,07H ;键盘输入开始INT 21HCMP AL,0DH ;ENTER键JE OVERCMP AL,41H ;是否小于AJB AGAINCMP AL,7AH ;是否大于zJA AGAINCMP AL,5AH ;是否大于ZJA C1ADD SUM[02H],01HMOV ALPHA[BX],ALINC BXJMP C2C1: CMP AL,61H ;是否小于aJB AGAINADD SUM[04H],01HMOV ALPHA[BX],ALINC BXC2: OUTCHAR ALJMP AGAINOVER: CRLF ;输入结束CMP BX,0H ;输入0个字母JE EXITMOV SUM[00H],BXMOV BX,0HMOV AX,0HLEA DI,ALPHASORT: INC AXCMP AX,SUM[00H]JE EXITMOV DL,[DI]MOV BX,AXNEXT: CMP DL,ALPHA[BX]JB NOXCHG DL,ALPHA[BX]NO: INC BXCMP BX,SUM[00H]JE RANKJMP NEXTRANK: MOV [DI],DLINC DIJMP SORTJMP EXIT;TOKEY:JMP KEYEXIT: CRLFOUTSTR MES2 ;输出提示语SHOWNUM SUM[00H]CRLFOUTSTR MES3 ;输出提示语SHOWNUM SUM[02H]SHOWRLT SUM[02H],0H,BIG,OBIGOUTSTR MES4 ;输出提示语SHOWNUM SUM[04H]SHOWRLT SUM[04H],SUM[02H],SML,OSMLKEY: MOV AH,1 ;程序功能结束INT 16HJZ KEYMOV AX,4C00HINT 21HCODE ENDSEND START。
汇编:汇编语言实现冒泡排序(loop指令实现)
15 CODES SEGMENT
16 ASSUME CS:CODES, DS:DATAS
17 START:
18
mov AX,DATAS
;待排序的内容的段地址
19
mov DS,AX
20
21
mov bx,offset buffer ;待排序的内容的偏移地址
22
mov si,0 ;外层循环起始下标0
23
xor cx,cx
网络错误503请刷新页面重试持续报错请尝试更换浏览器或网络环境
汇编:汇编语言实现冒泡排序( loop指令实现)
1 ;===============================
2 ;循环程序设计
3 ;loop指令实现
4 ;冒泡排序
5 ;for(int i=0;i<N;i++){
6 ; for(int h=0;j<N-1-i>;j++){
35 next1:
36
inc di
37
loop flag2
38
pop cx
;内层循环完毕时 出栈
39 next2:
40
inc si
41
loop flag142Βιβλιοθήκη 43 exit:44
mov ah,4ch
45
int 21H
46 CODES ends
47 end START
48 ;=====================
24
mov cl,10 ;设置外层循环次数
25
26 flag1:
27
mov di,0 ;内层循环起始地址下标0
28
push cx
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
L3: INC DI
;AH>=AL,不需交换,(AH)直接和后一个数比较,相当于 j++
CMP DI,100 ;判断内层循环是否结束
JB L2
;没结束,继续循环
;内层循环结束了
INC SI
;外层变量 SI 加一,相当于 i++
MOV DI,SI ;相当于 j=i
LOOP L1
;通过寄存器实现两个存储器数据间的交换 MOV AH,BYTE PTR[BX] ;基址寻址 MOV AL,BYTE PTR[BX+99] MOV MAX,AH MOV MIN,AL MOV AH,4CH ;返回操作系统 INT 21H CSEG ENDS END START
DH,BYTE PTR[BX+DI] ;找到 DH,BYTE PTR[BX+DI]
;min=mid+1 AX,DI L1
;key 和 a[mid]的比较 ;key<mid
L2: DEC MOV JMP
L3: MOV JMP
L4: MOV
DI ;max=mid-1 CX,DI L1 DL,'N' ;存入 DL,以待输出 L5 DL,'Y'
;相当于 i
L2: MOV AL,[BX+DI] ; L2 为内循环,(DI)为循环变量,相当于 j
CMP AH,AL
JAE L3
MOV DH,AH
;AH<Al,交换两个数
MOV AH,AL
MOV AL,DH
MOV [BX+DI],AL ;将交换后的数存入存储器
MOV [BX+SI],AH ;这两步很重要
解: (1)冒泡法
什么叫冒泡法呢?估计大家已经非常熟悉,在 C 语言中经常用到。用 C 语言实现冒泡 的代码如下:
for(int i=0;i<100;i++) for(int j=i+1;j<100;j++) { if(a[i]>a[j]) { int t=a[i]; a[i]=a[j]; a[j]=t; } }
MAX DB ? MIN DB ? DSEG ENDS CSEG SEGMENT ASSUME DS:DSEG,CS:CSEG START: MOV AX,DSEG MOV DS,AX ;————————————————到这,上面的均是模板 LEA BX,SCORE ;取数组的首地址 MOV CX,100 ;控制循环次数 XOR SI,SI ;将 SI 清零 XOR DI,DI ;将 DI 清零 L1: MOV AH,[BX+SI] ;用基变址寻址取操作数, L1 为外循环,(SI)为循环变量,
DSEG SEGMENT SCORE DB 31H,02H,15H,4H,5H,6H,7H,8H,9H,10H,90 DUP(05H) MAX DB ? MIN DB ?
DSEG ENDS CSEG SEGMENT
ASSUME DS:DSEG,CS:CSEG START: MOV AX,DSEG
MOV DS,AX
那么,用汇编语言怎么来实现呢?其实道理很简单,就是按照 C 语言的形式将其转换成汇编 语言。当然,还有其他的一些操作需要处理,如数据段„„
下面是汇编语言的冒泡排序:
DSEG SEGMENT SCORE DB 11H,02H,15H,32H,5H,6H,7H,8H,9H,10H,90 DUP(05H)
INT 21H 输出的字符需要先存在 DL 中。
折半查找:以处于区间中间位置的数据和给定值比较,若相等,则查找成功;若不等,则缩 小范围,直到新的区间中间位置的数据等于给定值或查找区间的大小小于零是为止。
首先介绍 C 语言版的折半查找: int search(int key) {
low=1; high=100; while(low<=high) {
if(a[i]<a[i-1])
;找到位置
{
a[0]=a[i];
a[i]=a[i-1];
for(int j=i-2;a[0]<a[j];j--)
a[j+1]=a[j];
;向后移
a[j+1]=a[0];
;插入数据
}
其中 a[0]不存放数据,充当转换的中间容器。数据从 a[1]—a[100]。
按照上面的代码将其转换成汇编版的插入排序法:
根据用户输入的一个 2 位十进制数,作为查找对象,在该数组中查找,若找到则显示 “Y”,若没找到则显示“N”。
思路: 输入:MOV AH,01H
INT 21H 一次只能输入一个字符,且字符的 ASCII 码值存放在 AL 中。要输入一个两位数,就需要连 续输入两个字符并将其转换成十进制数(因为分数是十进制数)。 输出:MOV AH,02H
Ax,Ax ;min 初始值为 0 CH,CH ;清零
AL,CL ;注意不能将“JG”写成“JA”,即应该是带符号数比较 ;否则当你输入“00”时,将不输出结果
MOV ADD SAR
DI,AX DI,CX DI,1
;实现 mid=(max+min)/2
CMP JZ L4 CMP JB L2 INC DI MOV JMP
利用汇编语言实现冒泡排序、直接插入排序、折半查找。 下面以例题的形式进行讲解。
例一:在内存 Score 缓冲区中存放有 100 个学生的成绩数据,为无符号字节数。 要求:
1、 用冒泡排序对数据从大到小排序; 2、 直接插入排序对数据从小到大排序; 3、 将最高分和最低分分别放在 MIN 和 MAX 单元中。
ASSUME DS:DSEG,CS:CSEG START: MOV AX,DSEG
MOV DS,AX
MOV INT MOV SUB MUL MOV MOV INT SUB ADD
AH,1 21H AH,10 AL,'0' AH DH,AL AH,1 21H AL,'0' DH,AL
;输入第一个字符 ;十进制数
L3: MOV DH,AL
; a[i]—>a[0]
MOV AL,DL
; a[i-1]—>a[i],虚假的,只是在寄存器中
MOV [BX+SI],AL ; a[i-1]—>a[i],真正的,在内存中
MOV DI,SI
; DI 相当于 j,i—>j
SUB DI,2
; j-2—>j
JS L5
;这一步很重要,防止数组越界
LOOP L1
L6: MOV AL,BYTE PTR[BX]
MOV AH,BYTE PTR[BX+99]
MOV MAX,AH
MOV MIN,AL
MOV AH,4CH ;返回操作系统
INT 21H
CSEG ENDS
END START
可以看出,上述代码的核心就是 C 代码的汇编语言翻译。 需注意:
① 最后将最大值和最小值分别存入 MAX、MIN 单元中时,不能直接从数组的存储单元存入 MAX 和 MIN 中,如下面的语句是错误的:
MOV L1: INC L2: MOV
MOV CMP JAE
CX,99 ;设置循环次数,注意不是 100,这主要由程序的写法决定的
SI
; i++
AL,[BX+SI]
; a[i]—>(AL)
DL,[BX+SI-1] ; a[i-1]t;=a[i-1]
;a[i] < a[i-1]
B、而且[]中也不能同时出现两个变址寄存器 SI 和 DI,如“MOV AX,[SI+DI+3] ” 是 错 误 的; C、如果在[]内加入了存储器,如“MOV AX,[BX+MAX]”,则此时的 MAX 代表着偏移地
址,而不是 MAX 所对应的数据的值。 ③ 在交换数据时,不仅要交换寄存器中的数据,而且要将存储器中的数据交换过来。
MOV MIN,BYTE PTR[BX] MOV MAX, BYTE PTR[BX+99]
这是编译错误,而不是逻辑错误。因为 CPU 指令系统的 MOV 指令要求其两个操作数不能同 时为存储器操作数。这是初学者经常会犯的错误。
下面将介绍折半查找。 例二:在内存 Score 缓冲区中存放有 100 个学生的成绩数据,为无符号字节数。设计程序完 成如下功能:
;输入第二个字符 ;最后的十进制数存放在 DH 中
MOV INT
AH,1 21H
;接收回车符<enter>
MOV MOV INT
DL,10 AH,2 21H
;输出换行
LEA MOV
BX,SCORE ;数组的首地址放在 BX 中 CL,99 ;max 初始值为 99
XOR XOR L1: CMP JG L3
L5: MOV INT
AH,2 21H
;输出结果
MOV AH,4CH
INT
21H
CSEG ENDS
END START
;返回操作系统
注意输入输出格式的控制。
总结:从以上的程序编辑过程来看,只要能将算法的 C 语言代码写出来,就能够将相应的汇 编程序写出来。当然你可能觉得这是不是有点麻烦——在写汇编程序之前还必须将相应的 C 语言程序写出来,其实这是编写汇编程序的初级阶段,等你熟悉了汇编以后,只要你知道算 法的思想,就能够跳过 C 代码的编写,直接进入汇编程序的编写。
其实软件开发中,在进行代码编写之前都需要画流程图、N—S 流程图等等,所以我们 得养成先画流程图再写程序的习惯。
要注意的几点: ① 数据段使用的 DUP 相当于 C 语言中的数组,可以很简便的输入很多数据,即使这些数据