Неправильная итерация цикла в Ассемблере
Использование nasm с 32-битным ассемблерным кодом дает неожиданный результат для моих текущих попыток написать цикл, который в основном меняет местами элементы вектора. При условии ESI
а также EDI
указать на два разных вектора (хранение double
ценности) и ECX
число n
описывающий поменять местами первый n
элементы из [ESI]
с первым n
элементы из [EDI]
мои попытки пока выглядят так:
; c-call: dswap(int n, double* dx, int unused1, double* dy, int unused2)
_dswap:
push ebp
mov ebp, esp
pusha
mov esi, [ebp+12] ; dx
mov edi, [ebp+20] ; dy
mov ecx, [ebp+8] ; n
; unused1 and unused2 obviously unused for the moment
mainLoop:
cmp ecx, 0
je exitFunction
mov eax, [esi + 4 * ecx]
mov ebx, [edi + 4 * ecx]
mov [esi + 4 * ecx], ebx
mov [edi + 4 * ecx], eax
dec ecx
jmp mainLoop
exitFunction:
popa
mov esp, ebp
pop ebp
ret
У меня неожиданное поведение. призвание dswap
на (1,2,3)
с (4,5,6)
а также n=3
меняются только первые два элемента в обоих векторах, что заставляет меня задуматься о том, что я здесь сделал неправильно.
2 ответа
Вы имеете дело с двойниками, но вы только умножаете ecx
на 4 (размер поплавка). Поскольку размер двойного числа равен 8, вы должны умножить на 8.
Другая проблема в том, что вы не уменьшаете ecx
прежде чем умножить на это. Если предположить, n
передается как 3, вы будете менять местами dx[3] с dy[3] на первой итерации, но это за пределами концов массивов. Чтобы это исправить, вы можете уменьшить ecx
прежде чем делать обмены.
Значения двойной точности обычно хранятся в 8-байтовых ячейках. В вашем цикле вы предполагаете ячейку размером 4 байта, поэтому поменяется только половина массива.