Assembly 什么';我的组装气泡排序有什么问题吗?
我正在使用基本伪代码/大纲在程序集中实现气泡排序:Assembly 什么';我的组装气泡排序有什么问题吗?,assembly,x86,masm,bubble-sort,Assembly,X86,Masm,Bubble Sort,我正在使用基本伪代码/大纲在程序集中实现气泡排序: for i in array if array[i] >= array[i+1] exchange array[i], array[i+1] 我的ASM代码: BubbleSort PROC mov EBX, LENGTHOF myArr .REPEAT mov ESI, 0 mov ECX, LENGTHOF myArr .
for i in array
if array[i] >= array[i+1]
exchange array[i], array[i+1]
我的ASM代码:
BubbleSort PROC
mov EBX, LENGTHOF myArr
.REPEAT
mov ESI, 0
mov ECX, LENGTHOF myArr
.REPEAT
mov EAX, [myArr + ESI]
.IF EAX >= [myArr + ESI + TYPE myArr] ; If (myArr[i] < myArr[i + 1])
xchg EAX, [myArr + ESI + TYPE myArr]
mov [myArr + ESI], EAX
.ENDIF
add ESI, TYPE myArr
dec ECX
.UNTIL ECX == 0
dec EBX
.UNTIL EBX == 0
ret
BubbleSort ENDP
BubbleSort程序
mov EBX,myArr的长度
.重复
电影ESI,0
mov ECX,myArr的长度
.重复
mov EAX,[myArr+ESI]
。如果EAX>=[myArr+ESI+类型myArr];If(myArr[i]
当我向我的教授展示我的实现时,他说这是“有点”像冒泡排序或“类型”冒泡排序。在告诉我们任务时,他说我们应该从阵列的后面开始,然后从后面移到前面。然而,我从前面开始,前后移动
我觉得我在正确的轨道上,代码可以正常工作,但我想正确地完成它
有人看到我把事情搞砸了吗?假设你的代码可以工作,那肯定是冒泡式的。向数组的任一端冒泡是可以的,因此不进行优化,例如使用外循环计数器(
EBX
)作为内循环的上限
简单化或天真并不能阻止它成为泡泡式的。(如果说有什么区别的话,那就是过于简单和幼稚才是泡沫式的关键。)
有关冒泡排序历史的更多信息,请参见,并讨论相关的跳转排序,以及是否使用布尔值作为早期输出 它提供的BubbleSort版本运行从
j=n-1
到1
(包括)的外部循环,因此内部循环可以将其用作上限。但是内部循环与您的循环相同,从k=0到j
,有条件地将A[j]
与A[j+1]
交换,从而使元素在数组末尾冒泡
该版本也会向上冒泡,从1运行到n-1(包括)。Wiki实际上有两个版本:第一个版本和你的一样幼稚,第二个版本在循环中递减n
。(两个Wiki版本都使用一个布尔变量来记录它是否进行了任何交换,这使算法复杂化,并挫败了冒泡排序的唯一目的/优点,即非常简单,代码也非常小。(例如,尽管它针对大小而非速度进行了大量优化。更正常的实现将类似于InsertionSort的大小。)
您的代码使用的MASM宏最终会浪费指令来重做检查(我假设。直到ECX==0
都不会利用dec ECX
已经根据ECX非零设置了标志的事实)。但是它确实有很好的do{}while()
循环结构,这是asm的惯用结构
顺便说一句,您的伪代码缺少外部循环。这只是BubbleSort的一个过程。但是,是的,迭代n
次将对n
元素数组进行排序。他认为您应该回到前面的原因是什么?如果您查看wikipedia上的纯伪代码实现,它的内部循环是前后循环的,并且它的外循环一直运行,直到不再发生交换。@Michael我不太确定,如果我没记错的话,他说它会比前后循环快。谢谢你提供的信息!我们被告知要使用。重复和。如果在这个练习中不使用cmp。@Small_Kitten:好的,那很好。我的意思是你不需要cmp
at all.dec ecx/jnz循环顶部
是在(--ecx)时在do{}的底部执行的正常操作
loop。隐藏这样的低效率是使用MASM高级构造的一个缺点。一旦你对asm有了更多的经验并了解了标志如何工作,没有它编写循环就很容易了。啊,我现在明白你的意思了,也感谢你!我想我已经在一些示例中看到了这种实现。汇编是非常不同的nt语言比其他语言都好,但到目前为止我很喜欢。@Small_Kitten:酷。如果你想读更多的东西,我在上面写了一个答案。另请参阅文档、手册等的更多链接,以及获取编译器来为你制作示例asm。(一般原则适用于MSVC和GCC)@Small_Kitten:顺便说一句,经常有人问关于堆栈溢出上的asm的家庭作业问题,他们要么讨厌它,要么完全不知所措(否则他们只需使用调试器单步解决自己的问题).因此,当有人有真正的问题时,这是一个很好的改变。无论如何,C与asm没有什么不同。一旦你了解了asm,你就可以考虑在编写C时CPU可以有效地做些什么,以及你希望代码如何编译。你甚至可以用do{}编写类似于asm的C结构虽然是循环,但通常编译器是好的。