самый эффективный способ инвертировать массив в сборке NASM? - PullRequest
2 голосов
/ 19 марта 2011

работает над инвертированием моего массива, у меня уже есть код, который будет распечатывать его, я думал о создании второго массива, сохранении его в нем, а затем распечатывая его, но есть ли более простой способ?

segment .bss  
    newarray    resd    40  
    segment .data  
    arrayis     db  "Inverted Array is: ", 0  
    space       db  ", ", 0  
    thanks      db  "Thanks", 0  
segment .text
    extern readdouble,print_string, read_int, writedouble, print_nl, print_int
    global invertarray
invertarray:
    pusha
    mov ebx, [ebp]  ;moves starting location of array1 into ebx
    mov edi, [ebp+12]   ;move quantity into edi 
    mov esi, 0      ;set esi to 0
    mov eax, arrayis    ;
    call    print_string    ;

    fld qword [ebx]
    mov ecx, [ebx]  ;move higher order into ecx
    mov edx, [ebx+4]    ;move lower order into edx
    call    writedouble

    mov eax, space  ;
    call    print_string    ;

topofloop:
    mov ecx, [ebx]  ;move higher order into ecx
    mov edx, [ebx+4]    ;move lower order into edx

    fld qword [ebx] ;move the first item of the stack onto st0
    add ebx, 8      ;increment to next location
    inc esi

    mov ecx, [ebx]  ;move first set of bits
    mov edx, [ebx+4]    ;move the second set of bits
    call    writedouble ;write the number

    mov eax, space  ;
    call    print_string    ;

    cmp esi, edi    ;compare to see if all items have been printed
    jz  done_loop   ;
    jmp topofloop   ;go back to top of the loop

done_loop:  
    popa
    ret

Ответы [ 2 ]

1 голос
/ 19 марта 2011

Я думаю, я бы использовал stosb и lodsb для этого.Lodsb получает байт от esi, а stosb сохраняет его для edi.используя repnz, вы также можете комбинировать его с ненулевым ecx (это цикл до ecx = 0).

0 голосов
/ 19 марта 2011

Строковые инструкции (stos *, lod *, scas *, cmps *) и инструкция цикла устаревшие и медленные (где-то я слышал). Я предпочел бы использовать что-то вроде:

    mov    esi, start_of_array       # esi points to array's begin
    mov    edi, esi
    add    edi, length_of_array      # and edi to array's end
    dec    edi                       # skip terminating null byte

loop:
    mov al, [esi]                   # load the dwords
    mov bl, [edi]
    mov [edi], al                   # and save them
    mov [esi], bl
    inc esi
    dec esi
    cmp esi, edi                     # check if we are before in array's middle
    jb loop

Это должно слово хорошо. Обратите внимание, что я загружаю eax с тем, что находится в [esi], но сохраняю его в [edi], то же самое для ebx. Конечно, вы должны настроить размер операндов в соответствии с typeof (массив).

EDIT: если вы хотите что-то быстрее, попробуйте это:

loop:
    mov ax, [esi]
    mov bx, [edi]
    xchg al, ah
    xchg bl, bh
    mov [esi], bx
    mov [edi], ax
    add esi, 2
    dec edi, 2
    cmp esi, edi
    jb loop

Это позволяет вам поменять 2 байта за раз, поэтому должен быть в два раза быстрее. Если вам интересно, xchg, xor swap и the swap занимают 3 такта, так что нет никакого преимущества в их использовании.

...