assembly 循环访问存储在x86程序集寄存器中的字符串(asm)

lyr7nygr  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(106)

假设我有一个很长的字符串,它的地址存储在rdi中,有没有办法遍历字符串中的每个字符?
这是我目前为止尝试的方法,但效率非常低,我仍然需要创建一个单独的方法来查找字符串的长度以终止循环。有没有更好的方法来处理这个asm x86-64?到目前为止,我只找到了this one),但这里我的字符串只存储在一个寄存器中,不能在开始时定义。
假设在函数之前,指向字符串的指针已经移动到%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
rseugnpd

rseugnpd1#

这是非常混乱的代码。为什么它有很多推力?为什么一次加载8个字节而不是一个字节一个字节地加载?你为什么要把东西不必要地搬来搬去?你的字符串零终止了吗?您可以执行以下操作:

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

相关问题