0

I am trying to reverse a string that I get from a C function using assembly stack.

this is my attempt so far :

section .text
    global do_Str
    extern printf

do_Str:

    push rbp
    mov  rbp, rsp
    mov  rcx, rdi
    
   

    mov r10, 0
    mov r9, 0
    ;mov r11, 0
    ;mov r13, 0

    label:
    
    cmp byte [rcx], 'a'
    jl cont
    cmp byte[rcx], 'z'
    jg cont
    and byte [rcx], 11011111b
    cont:
    
    cmp byte[rcx], '('
    jne contP
    mov byte[rcx], '<'
    contP:
    
    cmp byte[rcx], ')'
    jne contR
    mov byte[rcx], '>'
    contR:

    cmp byte[rcx],'A'
    jl contL
    cmp byte[rcx], 'Z'
    jg contL
    inc r9
    contL:


    




    inc r10
    inc rcx
    cmp byte [rcx], 0
    jnz label

;        mov r11, rdi
;        add r11, r10
;        dec r11
    
;        _revrse:
;        mov r13 , [r11]

;        mov r11 , [rdi]
;        mov rdi , [r13]
;         shr r10, 00000001

;        inc rdi
;        dec r11
;        cmp r11 , rdi
;        jne _revse

    done:
    mov ecx, r10d
    mov eax, esp
    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


    sub r10, r9
    mov rax, r10
    mov rsp, rbp
    pop rbp
    ret

I am not allowed to add more functions. This assembly code does two other things : changes two symbols and counts how many chars are not letters.

I have tried to use rbp and rsi but I get a core dumped error.

EliKnaffo
  • 354
  • 5
  • 17
  • 1
    `mov al, [esi]` is obviously going to segfault if the string isn't in the low 4GiB of memory. (e.g. if it's on the stack, its address won't be in the low 32 bits, so truncating the pointer will create an invalid pointer.) Always use `[rsi]` or other 64-bit registers in addressing modes - you don't want to truncate pointers to 32-bit. Especially not stack addresses; Linux puts the stack at the top of the user-space part of virtual address-space. – Peter Cordes Apr 24 '21 at 12:22
  • @PeterCordes I have tried replacing where I have esi with rsi but i still get a segfault error. I still can't figure out what I'm missing. – EliKnaffo Apr 24 '21 at 13:25
  • Did you still only take the low 32 bits of the stack pointer with `mov eax, esp` instead of `mov rsi, rsp`? Truncating a 64-bit pointer *at any point* will give you an invalid pointer that will segfault on deref. Note that even `inc esi` truncates RSI to 32 bits. [Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?](https://stackoverflow.com/q/11177137) – Peter Cordes Apr 25 '21 at 00:59
  • Use a debugger to look at register values, specifically the value of RSP, and see how your code truncates it when copying. – Peter Cordes Apr 25 '21 at 01:00
  • @PeterCordes I was able to solve this. I will post the solution soon. your comment helped me with identifying my problem. Do you have any recommended debuggers to use in linux for assembly? – EliKnaffo Apr 25 '21 at 08:32
  • I just use GDB. It's not great, but I already knew how to use it, and its `tui reg` mode is often decent, at least for integer registers. I've tried https://www.gdbgui.com/ but it was slightly slower than running GDB directly. – Peter Cordes Apr 25 '21 at 08:41

0 Answers0