汇编语言实现冒泡排序算法

 |
总阅读量


   初学汇编语言,自己便许下了用汇编实现冒泡排序算法的“宏愿”,现在也终于实现了一部分。用高级编程语言的思想指导低级编程语言来实现算法,在过去算奢侈,现在可能是一种妥协。我会随着课程的深入来改正这个程序。在这里记录历程。

版本1

include vcIO.inc
; 过程功能:冒泡排序
.data; set data segment
arr dd 10,2,3,2,5,21,32,12,43,12,33,43,54,66,87,89,00,4,2,6; 待排序数组
len1 byte ? ; 数组长度
len2 byte ? ;内层循环边界
fmt byte '%d ',0
.code
main proc
    mov len1,lengthof arr
    mov ebx,offset arr
    mov al,0h    ;外层循环变量

    ;外层循环体
lp:
    cmp al,len1
    jnb done; 结束循环

    ; 内层循环体
    mov ah, 1h; 内层循环变量
inner:
    ;内层循环判断索引部分
    mov cl,len1
    mov len2,cl
    sub len2,al
    cmp ah,len2
    jnb last
    movsx esi,ah    ;得到待比较的两个元素索引
    mov bl,ah
    sub bl,1
    movsx edi,bl
    mov ecx, arr[(type arr)*esi]
    mov edx, arr[(type arr)*edi]
    cmp ecx,edx
    jnb follow        ;交换元素
    mov edx,arr[(type arr)*esi]
    xchg edx,arr[(type arr)*edi]
    xchg edx,arr[(type arr)*esi]
follow:
    inc ah        ;内层循环更新
    jmp inner
last:
    inc al        ;外层变量更新
    jmp lp
done:
    xor ecx,ecx
    mov al,len1
prt:
    movsx ebx,al
    cmp ecx,ebx
    jnb fina
    mov edx, arr[(type arr)*ecx]
    pushad
        invoke printf,offset fmt,edx
    popad
    inc ecx
    jmp prt
fina:
    ret        ; return to windows
main endp    ; (insert additional procedures here)
end  main    ; end of assembly

版本2(子程序版)

  知道和运用之间总是隔着一个三维宇宙😁,这次更新带比例的的相对基址变址寻址,这样就不用单纯的通过改变索引(还是高级语言编程的习惯)来访问数组元素了。

include vcIO.inc
;过程功能
;主程序验证 ,子程序冒泡排序,通过堆栈传递参数
.data
arr dword 10, 2, 3, 2, 5, 21, 32, 12, 43, 12, 33, 43, 54, 66, 87, 89, 00, 4, 2, 6; 待排序数组
fmt byte '%d ',0
.code
main proc
    push lengthof arr ;数组长度压栈
    push offset arr      ;数组首地址压栈

    call bubbleSort

    add esp,8    ;堆栈平衡

    ; 打印结果
    mov ecx,lengthof arr
    mov ebx,offset arr
    xor esi,esi
again:
    mov eax,[ebx+4*esi]
    pushad
        invoke printf,offset fmt,eax
    popad
    inc esi
    loop again

bubbleSort proc
    push ebp    ;保护ebp内容
    mov ebp,esp ;取得最低地址堆栈指针
    push eax
    push ebx
    push ecx
    push edx
    push edi
    push esi
    mov ebx,[ebp + 8]    ;取出数组偏移地址
    mov ecx,[ebp + 12] ; 取出数组长度

    xor esi,esi    ;外层循环变量
outer:
    cmp esi,ecx
    jnb done    ;排序结束跳转

    push ecx
    sub ecx,esi    ;内层循环边界
    mov eax,ecx
    pop ecx

    xor edi,edi    ;内层循环变量
    inc edi        ;内层从1开始,比较arr[i]和arr[i-1]
inner:
    cmp edi,eax
    jnb next    ;内层循环结束

    push ecx    ; 交换准备

    ;待修改块
    ;带比例的基址变址寻址
    ;mov edx, [ebx + 4 * edi]
    ;dec edi
    ;mov ecx, [ebx + 4 * edi]
    ;inc edi

    ;带比例的相对基址变址寻址
    mov edx, [ebx + 4 * edi]
    mov ecx, [ebx + 4 * edi - 4]

    cmp edx, ecx
    jnb beyond
    ; 交换数据(待修改块)
    ;dec edi
    ;xchg edx, [ebx + 4 * edi]
    ;inc edi
    ;xchg edx, [ebx + 4 * edi]

    ;带比例的相对基址变址寻址
    xchg edx, [ebx + 4 * edi - 4]
    xchg edx, [ebx + 4 * edi]
beyond:
    pop ecx
    inc edi
    jmp inner
next:
    inc esi
    jmp outer
done:
    pop esi
    pop edi
    pop edx
    pop ecx
    pop ebx
    pop eax
    pop ebp
    ret
bubbleSort endp
    ret
main endp
end main