分享

冒泡排序的汇编语言与C语言程序对比

 喜欢站在山上 2022-04-13
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int i, j; //循环变量
  5. int MinIndex; //保存最小的值的下标
  6. int buf; //互换数据时的临时变量
  7. int a[] = {5, 5, 3, 7, 4, 2, 5, 4, 9, 1, 8, 6};
  8. int n = sizeof(a) / sizeof(a[0]); //存放数组a中元素的个数
  9. for (i=0; i<n-1; ++i) //n个数比较n-1轮
  10. {
  11. MinIndex = i;
  12. for (j=i+1; j<n; ++j) //每轮比较n-1-i次, 找本轮最小数的下标
  13. {
  14. if (a[MinIndex] > a[j])
  15. {
  16. MinIndex = j; //保存小的数的下标
  17. }
  18. }
  19. if (MinIndex != i) /*找到最小数之后如果它的下标不是i则说明它不在最左边, 则互换位置*/
  20. {
  21. buf = a[MinIndex];
  22. a[MinIndex] = a[i];
  23. a[i] = buf;
  24. }
  25. }
  26. printf('最终排序结果为:\n');
  27. for (i=0; i<12; ++i)
  28. {
  29. printf('%d ', a[i]);
  30. }
  31. printf('\n');
  32. return 0;
  33. }

以上是C语言程序

;用汇编语言实现实现冒泡排序,并将排序后的数输出

DATAS SEGMENT

A dw 5, 5, 3, 7, 4, 2, 5, 4, 9, 1, 8, 6

N=$-A ;计算数字所占的字节数

DATAS ENDS

//相当于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 // 相当于int a[] 中的数组a获得了一个确切的起始地址

MOV 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用于遍历存储的转化后的字符的位置(因为每个数字占4个字节,中间一个 空格)

SHOW: PUSH CX ;循环次数入栈

MOV DX,0 ;由于将要进行16位除需要置高16位为0

MOV AX,[SI] ;低16位为排序后的数

CALL DTOC ;调用DTOC将十进制数转换为字符串

CALL SHOW_STR ;调用SHOW_STR将一个数转化得到的字符串输出

ADD SI,2 ;下一个数

POP CX ;循环次数出栈栈

LOOP SHOW

MOV AH,4CH 汇编语言先要将每一个排好序的数字转换为字符串,然后再在屏幕上显示

INT 21H

整个上面这一段相当于for (i=0; i<12; ++i)

  • {printf('%d ', a[i]);}
  • ;冒泡排序

    BUBBLE PROC

    L1: PUSH CX ;将循环次数入栈

    LEA SI,A ;SI遍历DATAS数据段的数字

    L2: MOV AX,A[SI] ;将前一个数存于AX

    CMP AX,A[SI+2] ;比较前后两个数

    JBE NEXT ;如果前一个数小于或等于后一个数则继续本轮的比较

    XCHG AX,A[SI+2] ;否则,交换前后两个数的位置

    MOV A[SI],AX

    NEXT:ADD SI,2 ;下一个数

    LOOP L2 ;注意内层循环的次数已经确定了

    POP CX ;将循环次数出栈

    LOOP L1 ;下一轮比较

    RET

    BUBBLE ENDP

    //整个过程与C语言中的冒泡过程一样。注意两者的指针差别:C语言中就是简单的整型变量

    i,j,而汇编语言则要指定具体是哪个寄存器//

    ; 将十进制数转换为字符串并储存起来

    DTOC PROC

    S: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 S

    BACK:POP AX ;为了得到正确的IP值,需要出栈一次

    RET

    DTOC ENDP

    ;子程序定义开始,功能是分离被除数的各个位的数字

    ;公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N

    DIVDW PROC

    PUSH 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,默认余数在DX

    MOV CX,DX ;将余数转移到CX

    MOV DX,BX ;将商int(H/N)转移到dx,相当于int(H/N)*65536

    RET ;子程序定义结束

    DIVDW ENDP

    //C语言中没有这两段,全部隐藏在一句简单的printf('%d ', a[i]);之中//

    ;实现字符串的输出

    SHOW_STR PROC

    S2:MOV AH,2 ;输出数字转化后的字符串

    MOV DL,DS:[BP]

    INT 21H

    INC BP ;顺序输出

    DEC DI ;数字的位数减一

    JZ OK ;字符串输出完了就结束

    JMP S2 ;否则继续输出

    OK:MOV AH,2 ;输出空格

    MOV DL,0

    INT 21H

    RET

    SHOW_STR ENDP

    //C语言中也没有这段,同样全部隐藏在一句简单的printf('%d ', a[i]);之中//

    CODES ENDS

    END START

    由以上对比可以看到,汇编语言中的数字、字符、变量等的地址分配细节,都被高级语言隐藏了,这个过程其实也是一个程序的编译过程;同样数字到字符的转换过程也被隐藏了。所以,用高级语言编写同一个程序,就比用汇编语言要简单得多。

      本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
      转藏 分享 献花(0

      0条评论

      发表

      请遵守用户 评论公约

      类似文章 更多