【问题标题】:Assembly bubble sort swap装配冒泡排序交换
【发布时间】:2012-07-14 22:13:54
【问题描述】:

我正在尝试在 x86 程序集中进行冒泡排序(是的,它必须是冒泡排序,因为我不关心针对不同类型排序的速度优化)并且由于某种原因,我的代码不会交换必要的价值观。这是我的代码

mov eax, list                   ;store list in eax
mov edx,[eax+4*edi-4]           ;temp = var1
cmp edx,[eax+edi*4]             ;compare
JLE SECOND_LOOP                 ;jump if var1 < var2
mov [eax+4*edi-4],[eax+edi*4]   ;var1 = var2
mov [eax+edi*4], edx            ;var2 = temp
jmp SECOND_LOOP

在应该将 temp 加载回地址的最后一条 mov 指令中,它..没有。 EAX 寄存器具有包含我的值列表的数组的起始地址

0x*starting address* 0a 00 00 00 ec ff ff ff 05 00 00 00 0c 00 00 00 1e 00 00 00 fb ff ff ff ea
0x*address after   * ff ff ff 37 00 00 00 34 00 00 00 00 00 00 00

并且下一个地址包含更多的数字。在十进制中,数字是10 -20 5 12 30 -5 -22 55 52 0。基本上现在我正在尝试将FFFFFFEC 移动到0000000A,然后将0000000A 移动到FFFFFFEC。我可以将它存储到我的临时寄存器 EDX 中,但不能将 EDX 的值存储到特定地址中。有什么帮助吗?

【问题讨论】:

  • 嗯,是的,它没有。但是我只是将数据放入另一个寄存器并使用了 mov 指令。
  • 相关:stackoverflow.com/questions/17802947/… 有一个相当干净的 MASM 32 位交换实现,用于 32 位整数的冒泡排序。

标签: assembly x86 bubble-sort


【解决方案1】:

我想我会使用指向列表中当前位置的指针,而不是每次使用时都需要缩放的索引:

    mov esi, offset list
top:
    mov edi, esi
inner:
    mov eax, [edi]
    mov edx, [edi+4]
    cmp eax, edx
    jle no_swap
    mov [edi+4], eax
    mov [edi], edx
no_swap:
    add edi, 4
    cmp edi, list_end - 4
    jb inner
    add esi, 4
    cmp esi, list_end - 4
    jb top

【讨论】:

  • 请注意,xchg 带有内存非常慢,因为它是原子的(隐式 lock)。仅在以牺牲性能为代价优化代码大小时才使用此选项(可能是 10 倍)。在 codegolf.stackexchange.com/questions/77836/sort-an-integer-list/… 中查看我的 cmets。冒泡排序交换很多,在 cmp 之前加载到 edx 会更有意义,所以“交换”只是两个 mov 存储。或者更好的是,避免在递增 edi 时重新加载刚刚存储的值,使 [edi+4] 本次迭代进入 [edi] 下一次迭代。
  • @PeterCordes:我认为使用冒泡排序非常可靠地表明您不关心性能,但即便如此我认为xchg 是有点严厉的惩罚。你可以做很多事情来进一步优化它,但直到/除非你至少切换到插入排序。
  • 在某些情况下,您希望针对代码大小进行优化(冒泡排序或跳转排序实际上在 asm 中对此很有用),但要考虑 一些 性能。不过,在微控制器上,这种情况更有可能发生,您找不到太多 x86。是的,选择或插入排序几乎同样紧凑且速度更快。
  • @PeterCordes:我必须编写一些代码才能绝对确定,但插入排序必须大于冒泡排序并不是很明显(至少对我而言) .
  • @PeterCordes:这个insertion sort 的长度(以字节为单位)与上面的冒泡排序相同(并且以基本相同的风格编写——两者都没有真正尝试打高尔夫球)。跨度>
【解决方案2】:

这部分代码:

mov edx,[eax+edi*4]
mov [eax+edi*4], edx

实际上不会改变内存中的任何内容,它会从内存中读取一个值并将其写回它刚刚从那里获取的位置。

顺便说一句,您可能对xchg 指令感兴趣。

【讨论】:

  • 哇,我不敢相信我犯了这样一个基本错误并错过了它。当我查找 xchg 并意识到它的目的时,我的任务(这是一项家庭作业)要求我使用 EDX 作为临时寄存器。我更改了代码,但出现错误:操作数类型不正确。我还没有调试,因为当我发现时才发布,但如果你有建议,我很乐意听到。
  • 我不仅不能使用 xchg,而且我的 EAX 寄存器有列表的起始地址,因为我的 edx 有一个数字的值,所以 xchg-ing 它只会切换地址和数值,不要在内部切换数字
  • 你不能使用mov从一个内存移动到另一个内存。有效的操作数组合可以总结如下:reg/mem + reg/imm。没有mem + mem。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-09
  • 2012-07-05
  • 1970-01-01
相关资源
最近更新 更多