这个程序适用于x86中的反向数组(交换),但当元素数为奇数时它有runTime Error
.data
arr dword 9 dup (1) ; if elements=10 no problem ..!!
.code
main proc
mov ecx, (lengthof arr )
mov esi,0
mov edi,(lengthof arr-1) * type arr
lp:
mov eax , arr[esi]
xchg eax , arr[edi]
mov arr[esi] ,eax
add esi, type arr
sub edi, type arr
dec ecx
loop lp
retn
main endp
end main
答案 0 :(得分:0)
loop
already decrements ecx
,因此您遇到与Issue With Using dec to Create a Delay相同的问题。
dec ecx
loop lp
与
相同dec ecx
dec ecx
jnz lp
或
sub ecx, 2
jnz lp
如果计数器从奇数开始,它从1变为-1,因此零检验永远不会成立。如果您使用jg
进行循环,那么它就会正常运行。因此,您使用esi
和edi
运行您正在循环的数组的末尾。
如果您在调试器中单步执行循环时看到ecx
的值发生了变化,那么您很容易看到这一点。 (有关使用gdb for asm的提示,请参阅x86标记wiki的底部。
代码审核:
除非您需要原子读取 - 修改 - 写入功能(隐式xchg
前缀),否则不要将lock
与内存一起使用,因为它 比仅使用单独加载/存储。
您还会破解调用者的esi
和edi
值,这些值在大多数ABI中都会被保留。
不要将ecx
用作循环计数器,因为您已经使用esi和edi作为索引。只要cmp / ja
他们在彼此通过时就停止循环。 loop
指令在大多数情况下是一个糟糕的选择,因为它很慢并且通常你已经在另一个寄存器中有一些作为循环计数器的东西。
e.g。
main proc
push esi
mov esi, OFFSET arr ; not just arr, since this isn't NASM
lea ecx, [esi + (lengthof arr-1) * type arr] ; ecx = pointer to last element
swaploop:
mov eax, [esi] ; need to use different register sizes if type arr isn't 4 bytes
mov edx, [ecx]
mov [esi], edx ; store to opposite locations
mov [ecx], eax
add esi, type arr
sub ecx, type arr
cmp esi, ecx
jb swaploop ; while(low < high) // (unsigned compare)
pop esi
ret
请注意mov eax, [esi]
/ add esi, 4
could be a lodsd
instruction,但是您需要为商店地址设置-4位移,而且可能会更慢。