Iterating through string stored in register in assembly x86 (asm)

71 Views Asked by At

Say if I have a very long string whose address is stored in rdi, is there anyway I can iterate through every character of the string?

This is what I tried so far, but it's very inefficient and I still need to create a separate method to find the length of the string to terminate the loop. Is there a better method for this asm x86-64? I've only found this one) so far but here my string is only stored in a register and cannot be defined at the start.

Assume that before function, the pointer to the string is already moved to %rdi:


.global function

test:       .asciz "\nTest:`%c"

function:

pushq   %rbp
movq    %rsp, %rbp

pushq   %rdi
pushq   %rdi
movq    (%rdi)  %rax
movq    $0, %rbx
movq    $8, %rdx
pushq   %rax
pushq   %rbx

loop:
movzb   %al, %rcx
movq    %rcx, %rsi
movq    $test, %rdi
call    printf
movq    (%rsp), %rbx
movq    8(%rsp), %rax
movq    $8, %rdx
shr $8, %rax
incq    %rbx
cmpq    %rbx,%rdx
jne loop

next_byte:
add $8, %rdi
movq    (%rdi), %rax
movq    $0, %rbx
pushq   %rcx
pushq   %rdx
pushq   %rax
pushq   %rbx
jmp loop

movq    %rbp, %rsp
popq    %rbp
ret
1

There are 1 best solutions below

0
Jester On BEST ANSWER

That's very confusing code. Why does it have tons of pushes? Why do you load 8 bytes at a time instead of going byte by byte? Why do you move stuff around unnecessarily? Is your string zero terminated? You could do:

function:
    push %rbx              # save a call-preserved register
    mov %rdi, %rbx         # use it to save the current position across calls
loop:                      # while(1) {
    movzbl (%rbx), %esi       # zero-extending byte load
    test %esi, %esi
    jz done                   # if (*ptr == 0) break;

    lea test(%rip), %rdi
    xor %eax, %eax            # AL = 0 args in XMM regs
    call printf@plt           # printf("Test: %c", *ptr)

    inc %rbx                  # ptr++
    jmp loop               # }
done:
    pop    %rbx            # restore the caller's reg we saved earlier
    ret