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
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