Неправильная итерация цикла в Ассемблере

Использование 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 байта, поэтому поменяется только половина массива.

Другие вопросы по тегам