在 nasm 汇编中反转数组的最有效方法?

发布于 2024-10-24 04:54:41 字数 1410 浏览 2 评论 0原文

正在反转我的数组,我已经有代码可以将其打印出来,我正在考虑创建第二个数组,将其存储到其中,然后将其打印出来,但是有没有更简单的方法?

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

working on inverting my array, i have code already taht will print it out, i was thinking of creating a second array, storing it into it, then printing that one out, but is there an easier way?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

淡淡離愁欲言轉身 2024-10-31 04:54:41

我想我会使用 stosb 和 lodsb 来做到这一点。 Lodsb 从 esi 获取一个字节到 al,stosb 将其存储到 edi。使用repnz,您还可以将其与非零的ecx结合起来(这是一个循环,直到ecx = 0)。

I think i would use stosb and lodsb in order to do that. Lodsb gets a byte to al from esi and stosb stores it to edi. using repnz you can also combine it with ecx being non zero (it's a loop till ecx = 0).

风铃鹿 2024-10-31 04:54:41

字符串指令(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

这应该很好。请注意,我使用 [esi] 中的内容加载 eax,但将其保存在 [edi] 中,ebx 的语音相同。当然,您必须根据 typeof(array) 调整操作数的大小。

编辑:
如果你想要更快的东西,试试这个:

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,异或交换和与交换都需要 3 个时钟周期才能完成,因此使用它们没有任何优势。

String instructions (stos*, lod*, scas*, cmps*) and the loop instruction are deprecated and slow (I heard that somewhere). I'd rather use something like:

    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

This should word fine. Note that I load eax with what's in [esi] but save it in [edi], same speech for ebx. Of course you have to adjust operands' size according to typeof(array).

EDIT:
if you want something faster try this:

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

This allows you to swap 2 bytes at time, so it should be two times faster. If you're wondering, xchg, the xor swap and the and swap take both 3 clock cycles to complete, so no advantage in using them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文