Skip to content

Instantly share code, notes, and snippets.

@seisvelas
Last active December 27, 2020 03:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seisvelas/ad57cacb26e30af74408f2a97587d598 to your computer and use it in GitHub Desktop.
Save seisvelas/ad57cacb26e30af74408f2a97587d598 to your computer and use it in GitHub Desktop.
String with backspaces function in ASM - broken because I can't correctly move one byte between two pointers
global strclr
extern printf
extern malloc
section .text
strclr:
sub rsp, 8
; callee reserved registers
push rbx
push rcx
push rdi
xor rax, rax
call printf
pop rdi
mov r8, rdi
mov r12, 1
push rax
; r12: char count
xor rax, rax
final_char_count:
cmp BYTE [r8], 0
je after_count
cmp BYTE [r8], '#'
je found_backspace
inc r12
jmp count_epilogue
found_backspace:
cmp r12, 1
je count_epilogue
dec r12
count_epilogue:
inc r8
jmp final_char_count
after_count:
pop rax
; copy first arg into r8 so we can save the address
; of where the string began (for our loop condition)
mov r8, rdi
; Get last character in string
mov rdx, 0
get_string_end:
cmp BYTE [r8], 0
je end_attained
inc r8
inc rdx
jmp get_string_end
end_attained:
push rdi
push r8
push rdx
xor rax, rax
push r12
call malloc
mov rbx, rax
add rbx, r12
add rsp, 8
pop rdx
pop r8
pop rdi
xor rax, rax ; RAX <- the result
mov BYTE [rbx], 0 ; null terminator for output buffer
mov r9, 0
algorithm:
cmp rdx, 0
jl return
cmp BYTE [r8], '#'
jne non_backspace
inc r9
jmp algo_postscript
non_backspace:
cmp r9, 0
je no_pending_backspaces
dec r9
jmp algo_postscript
no_pending_backspaces:
dec rbx
mov al, BYTE [r8]
mov [rbx], al
algo_postscript:
dec r8
dec rdx
jmp algorithm
return:
lea rax, [rbx]
; restore callee reserved registers
pop rcx
pop rbx
add rsp, 8
ret
@seisvelas
Copy link
Author

The crux of the brokenness is this section:

    mov rdi, [r8]
    mov rsi, [output_buffer+rax]
    movsb

movsb probably doesn't work how I'm expecting it to. I need to learn how to do this correctly. Or, I could hack around it by using external C functions (which I have access to in this context, since it's a codewars problem) to reverse the string and copy stuff. But that's just punting the real problem down the line, which is my ignorance of how to transfer one byte between two pointers using raw assembly.

@seisvelas
Copy link
Author

Perhaps a simpler hack (that still isn't sufficient educationally, but still) would be to use AL, which is the first byte of RAX!

@seisvelas
Copy link
Author

Okay, fixed. The function works now, but crashes in the codewar's test because they try to free() the pointer to the string this function returns. That's no good because this function is writing to a buffer in .bss, so free'ing the pointer is invalid. To fix this, I'll have to get memory dynamically (ie, mmap syscall or C malloc)

@seisvelas
Copy link
Author

Grr, everything works fine on machine and in sample tests. Then real tests all crash. So, clearly in the real tests something else is being done with the pointers I return, or am given.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment