Trouble reversing a string in assembly

前端 未结 2 824
孤街浪徒
孤街浪徒 2021-01-07 06:08

I am trying to reverse a string in assembly. However my code does not seem to work correctly. I added a newline string for better readability.

I am using linux and n

相关标签:
2条回答
  • 2021-01-07 06:45

    The way to reverse a string by swapping characters is to swap the first and last, then the second and next to last, etc. In C, you would write:

    for (i = 0; i < len/2; ++i)
    {
        c = s[i];
        s[i] = s[len-i-1];
        s[len-i-1] = c;
    }
    

    In assembly language, the easiest way is to set up the ESI and EDI registers to point to the start and end of the string, then loop. At each iteration, you increment ESI and decrement EDI. The result looks something like this:

    mov ecx, helloLen
    mov eax, hello
    mov esi, eax  ; esi points to start of string
    add eax, ecx
    mov edi, eax
    dec edi       ; edi points to end of string
    shr ecx, 1    ; ecx is count (length/2)
    jz done       ; if string is 0 or 1 characters long, done
    reverseLoop:
    mov al, [esi] ; load characters
    mov bl, [edi]
    mov [esi], bl ; and swap
    mov [edi], al
    inc esi       ; adjust pointers
    dec edi
    dec ecx       ; and loop
    jnz reverseLoop
    
    0 讨论(0)
  • 2021-01-07 06:55

    When I did this for an interview, I came up with this... It is a bit Microsoft specific, but it's roughly the same as what @Jim Mischel wrote, except this calculates the length of the string rather than being passed it etc.

    This function is naked, so since there's no prolog or epilog you do have to be careful about what registers you can use. (Unless you push and pop if you use them. In this example, I'm not using any registers that need to be preserved)

    #define USE_STRLEN 0                                    ; Use strlen to find string length?
    
    __declspec(naked) uint8_t* string_rev(uint8_t* s)
    {
        __asm
        {
                  mov    eax, dword ptr[esp + 4]            ; Get the address of string
                  test   eax, eax                           ; Been passed a null pointer?
                  jz     lp_3
    #if (USE_STRLEN)
                  push   eax                                ; Push string address onto stack
                  call   strlen
                  pop    ecx                                ; Pop our string back off the stack
                  xchg   ecx, eax                           ; String length in eax
    #else
                  or     ecx, 0ffffffffh                    ; Start ecx at -1
            lp_1:
                  inc    ecx
                  test   byte ptr[eax + ecx], 0ffh          ; Test string byte for zero
                  jnz    lp_1                               ; ecx = string length
    
    #endif
                  lea    edx, dword ptr[eax + ecx - 1]      ; edx = last character in string
                  and    ecx, -2                            ; Is string 1 character or less?
                  jz     lp_3
            lp_2:
                  mov    cl, byte ptr[edx]
                  mov    ch, byte ptr[eax]
                  mov    byte ptr[eax], cl
                  mov    byte ptr[edx], ch
                  inc    eax
                  dec    edx
                  cmp    edx, eax                           ; Loop whilst one pointer is less
                  ja     lp_2                               ; than the other (equiv. len/2)
            lp_3:
                  ret                                       ; Reversed string in eax
        }
    }
    
    0 讨论(0)
提交回复
热议问题