You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

汇编实现冒泡排序求助:现有代码未得到预期排序结果

冒泡排序汇编代码问题排查与修复

问题背景

尝试将C语言冒泡排序精确翻译成x86汇编,初始数组为{5,1,4,2,8},预期排序结果为{1,2,4,5,8},但现有代码无法得到正确结果,需排查并修正。

参考C语言冒泡排序代码

// C program for implementation of Bubble sort
#include <stdio.h>

int arr[] = { 5, 1, 4, 2, 8 };

void swap(int* xp, int* yp)
{
    int temp = *xp;
    *xp = *yp;
    *yp = temp;
}

// A function to implement bubble sort
void bubbleSort(int arr[], int n)
{
    int i, j;
    for (i = 0; i < n - 1; i++)

        // Last i elements are already in place
        for (j = 0; j < n - i - 1; j++)
            if (arr[j] > arr[j + 1])
                swap(&arr[j], &arr[j + 1]);
}

// Driver program to test above functions
int main()
{
    int n = sizeof(arr) / sizeof(arr[0]);
    bubbleSort(arr, n);
    return 0;
}

现有汇编代码的核心错误

  • elementswap函数逻辑完全错误:当前代码直接交换栈上的参数地址,而非地址指向的内存值,完全不符合swap函数的功能。
  • bubblesort参数读取颠倒:C代码中bubbleSort的参数顺序是(数组地址, n),对应汇编栈帧中[EBP+8]是数组地址、[EBP+12]是n,但现有代码搞反了两者,导致循环边界计算彻底错误。
  • 内层循环数组指针未重置:每次进入innerloop时,edx未重置为当前轮次的数组起始位置,导致后续比较的元素位置混乱。
  • swap调用参数传递错误:调用elementswap时未传入正确的相邻元素地址,而是错误压入寄存器值,不符合C代码中swap(&arr[j], &arr[j+1])的参数要求。
  • 循环边界计算错误:C代码中外层循环i < n-1、内层循环j < n-i-1,现有汇编中sub ebx,2这类处理完全偏离逻辑,导致循环次数错误。

修正后的完整汇编代码

.386
.model flat, stdcall
.stack 4096
ExitProcess proto, dwExitCode:dword

.data
myarr dd 5, 1, 4, 2, 8  ; 初始数组

.code
elementswap proc
    push ebp
    mov ebp, esp
    push eax
    push ebx
    push ecx

    ; 读取参数: [EBP+8] = xp, [EBP+12] = yp
    mov eax, [ebp+8]   ; eax = xp
    mov ebx, [ebp+12]  ; ebx = yp
    mov ecx, [eax]     ; ecx = *xp (temp)
    mov edx, [ebx]     ; edx = *yp
    mov [eax], edx     ; *xp = *yp
    mov [ebx], ecx     ; *yp = temp

    pop ecx
    pop ebx
    pop eax
    mov esp, ebp
    pop ebp
    ret 8  ; 清理2个4字节参数,符合stdcall调用约定
elementswap endp

bubblesort proc
    push ebp
    mov ebp, esp
    push esi
    push edi
    push edx
    push ebx

    mov esi, 0          ; i = 0
outerloop:
    mov ebx, [ebp+12]   ; ebx = n
    sub ebx, 1          ; ebx = n-1
    cmp esi, ebx        ; 比较i和n-1
    jge exit_outerloop  ; i >= n-1时退出外层循环

    mov edi, 0          ; j = 0
innerloop:
    mov ebx, [ebp+12]   ; ebx = n
    sub ebx, esi        ; ebx = n - i
    sub ebx, 1          ; ebx = n - i -1
    cmp edi, ebx        ; 比较j和n-i-1
    jge exit_innerloop  ; j >= n-i-1时退出内层循环

    ; 计算arr[j]和arr[j+1]的地址
    mov edx, [ebp+8]    ; edx = arr起始地址
    mov eax, edi
    shl eax, 2          ; eax = j*4 (int占4字节)
    add edx, eax        ; edx = &arr[j]
    mov ecx, edx
    add ecx, 4          ; ecx = &arr[j+1]

    ; 比较arr[j]和arr[j+1]
    mov eax, [edx]
    cmp eax, [ecx]
    jle skip_swap       ; arr[j] <= arr[j+1]则不交换

    ; 调用swap函数
    push ecx            ; 第二个参数: &arr[j+1]
    push edx            ; 第一个参数: &arr[j]
    call elementswap

skip_swap:
    inc edi             ; j++
    jmp innerloop

exit_innerloop:
    inc esi             ; i++
    jmp outerloop

exit_outerloop:
    pop ebx
    pop edx
    pop edi
    pop esi
    mov esp, ebp
    pop ebp
    ret 8  ; 清理2个4字节参数,符合stdcall调用约定
bubblesort endp

main proc
    push ebp
    mov ebp, esp

    ; 调用bubblesort(arr, n)
    mov eax, LENGTHOF myarr
    push eax            ; 第二个参数: n
    push OFFSET myarr   ; 第一个参数: arr地址
    call bubblesort

    invoke ExitProcess, 0
main endp
end main

关键修正说明

  • elementswap函数修复:正确读取参数中的两个地址,交换地址指向的内存值,使用寄存器暂存临时值,同时通过ret 8自动清理栈上的两个参数,符合stdcall调用约定。
  • bubblesort参数修正:正确读取[EBP+8]为数组地址,[EBP+12]为n值,严格按照C代码逻辑计算循环边界。
  • 内层循环指针重置:每次进入innerloop时,重新计算当前j对应的数组元素地址,确保比较的是arr[j]和arr[j+1]。
  • swap参数正确传递:计算出两个相邻元素的地址,按顺序压栈后调用elementswap,完全匹配C代码的参数传递逻辑。
  • 循环边界逻辑对齐:外层循环条件对应i < n-1,内层循环条件对应j < n-i-1,保证循环次数正确。

内容的提问来源于stack exchange,提问作者Amalia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 11:15:28