【问题标题】:C assembly implement bubble sortC汇编实现冒泡排序
【发布时间】:2020-08-23 10:18:04
【问题描述】:

我必须用 C 语言编写一个带有汇编工具的冒泡排序。 我的 C 代码如下所示:

#include <stdio.h>

extern int arraysort(int array[],int length);
int main () {
    int array[]= {7,4,3,6,2,1};
    int length = 6;
    printf("Unsorted array: %d,%d,%d,%d,%d,%d\n",array[0],array[1],array[2],array[3],array[4],array[5]);
    arraysort(array,length);
    printf("Sorted array: %d,%d,%d,%d,%d,%d\n",array[0],array[1],array[2],array[3],array[4],array[5]);

    return 0;
}

我的汇编代码如下:

.intel_syntax noprefix

.text
.global arraysort
arraysort: # int sortarray(int array[],int length)

    #function prologue
    push ebp
    mov ebp, esp
    # function prologue end

    push ebx   # save ebx for cdecl convection
    # 1.argumentum [ebp + 4*2] this is the array
    # 2.argumentum [ebp + 4*3] this is the length

    mov ecx, [ebp + 12]   #array length (6)
    dec ecx               #array length (5)
    mov edx, 1            #variable j
    mov esi, [ebp + 8] #array address
loop1:
      cmp ecx, 0  # (int i =length; i> length;i--)
      jg end
    loop2:
    mov eax, [esi + 4*ecx] #array[0]
    mov ebx, [esi + 4*edx] #array[1]
    cmp eax, ebx #if eax > ebx jump to csere
    jg swap
    dec ecx  #i--
    inc edx#j++
    jz end
    jmp loop2

swap:
    mov [esi + 4*edx], eax #change the two elements
    mov [esi + 4*ecx], ebx
    jmp loop2

end: 
    pop ebx
    mov esp, ebp
    pop ebp
    ret

我不知道是什么问题,我为此苦苦挣扎。 如果我将第一个循环 jg 更改为 jl 我得到无限循环:/ 对不起我的英语和汇编编码技能,但我仍在学习这种语言。 请帮我!谢谢

【问题讨论】:

  • 代码的实际行为(又名输出)是什么?
  • 而且我看不出你是如何设法使用 loop1 的。没有jmp loop1 或那种代码
  • 实际输出是:程序打印未排序的数组,函数不做任何事情并打印排序的数组。我忘了写 jmp loop1 也许这是问题所在,这就是我得到无限循环的原因与 jl ?
  • 作为提示,我会用 C 编写它并使用 Godbolt 输出到汇编程序。如果你上交就作弊,但会给你一个有效的例子。
  • @tadman:我很确定这只是学习 asm 的功课。在分支布局、寻址模式的选择和其他方面有很多小的低效率,并且没有明显的任何优化迹象(尽管有些方面是正确的,比如将条件分支放在循环的底部)。这也是从数组的开头/结尾开始沿相反方向行走的索引,而不是比较相邻元素,所以它不是冒泡排序,根本不可能真正排序。如果是冒泡排序,您可能希望在寄存器中重用a[i+1] 作为下一次迭代的a[i]

标签: c assembly x86 intel bubble-sort


【解决方案1】:

这是主要问题:

    mov ecx, [ebp + 12]   #array length (6)
    dec ecx               #array length (5)
    mov edx, 1            #variable j
    mov esi, [ebp + 8] #array address
loop1:
      cmp ecx, 0  # (int i =length; i> length;i--)
      jg end

在那里关注ecx。你基本上是在说if(--length &gt; 0) goto end;,所以你跳过了整个函数。

现在,一旦您解决了这个问题,您就会开始遇到段错误。原因如下:

    dec ecx  #i--
    inc edx#j++
    jz end

相当于--i; if(!++j) goto end;。结果,您的循环将运行比您想要的更多的迭代(直到j 溢出,但实际上它会首先出现段错误)。我猜你打算切换dec ecxinc edx,这样循环就会在i 变为0 时结束。

无论如何,如果也修复了这个问题,您的代码将返回一个更新后的数组,但它仍然是错误的。至此,只是因为你的冒泡排序错误,而不是因为任何与汇编相关的错误,所以我就到此为止。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 1970-01-01
    • 2020-09-26
    • 2014-10-26
    相关资源
    最近更新 更多