64 位的 x86 汇编,从函数返回字符串并将其放入数组中

问题描述 投票:0回答:1

我使用 64 位程序集并有两个不同的文件。其中一个文件更改了字符串,以便该字符串添加了随机的新字符。另一个文件包含一个数组。

这是来自编辑字符串的文件:

    returnString:
        mov rax, newString
        ret

这是数组及其设置方式:

section .bss
    array: resq 4
    allocString: resb 128

section .text
_start:
   mov qword[array], defaultMes0
        xor r8,r8
        add r8, 8

        mov qword[array + r8], defaultMes1
        add r8, 8

        mov qword[array + r8], defaultMes2
        add r8, 8

        mov qword[array + r8], defaultMes3
        add r8, 8

这是应该将字符串从函数移动到数组中的函数:

rev:

        mov rax, 8
        movzx rdx, byte [index] ; Clear rdx to avoid issues with imul

        imul rdx ; Multiply index by 8

        mov rdi, qword [array + rax]

        call stringEdit

        lea rbx, [allocString]
        
        translateLoop:
            mov dl, [rax]
            mov [rbx], dl

            ;both incremented and counter also incremented
            inc rax
            inc rbx

            ;comparison, if less than bl then done until it is equal to enterNum (place of split)
            cmp byte[rax], 0x0
            jne translateLoop
        
        mov rax, 8
        movzx rdx, byte [index] ; Clear rdx again

        imul rdx ; Multiply index by 8

        mov qword [array + rax], rbx

如果使用 print 函数输出字符串,它将是空白的(例如,它不会输出任何内容)。

我尝试过:

    returnString:
        mov rax, [newString]
        ret

但它无法正常工作。我还尝试将函数的输出直接放入字符串中,如下所示,但这也不起作用(无论是引用还是取消引用 newString 时)。如果取消引用 newString,则在打印时会导致段错误,并且如果未引用,则调用该函数的任何其他时间,数组中的所有内容都指向同一对象,因此调用此函数的任何数组索引都将共享相同的结果.

call stringEdit

mov qword [array + rax], rdi ;;moved it to the rdi before
function file assembly x86 x86-64
1个回答
0
投票

我尝试过做

returnString:
    mov rax, [newString]
    ret

这将返回新字符串内容的前八个字节。您的第一次尝试是正确的,

mov rax, newString
返回新字符串的地址。


mov qword[array], defaultMes0
xor r8,r8
add r8, 8
mov qword[array + r8], defaultMes1
add r8, 8
mov qword[array + r8], defaultMes2
add r8, 8
mov qword[array + r8], defaultMes3
add r8, 8

无法将 64 位立即数移至内存,并且 R8 的使用过于复杂,因为您可以更轻松地使用

+8
+16
+24
进行偏移。

lea  rax, [rel defaultMes0]
mov  [rel array], rax
lea  rax, [rel defaultMes1]
mov  [rel array + 8], rax
lea  rax, [rel defaultMes2]
mov  [rel array + 16], rax
lea  rax, [rel defaultMes3]
mov  [rel array + 24], rax

有关 RIP 相对寻址的信息


mov rax, 8
movzx rdx, byte [index] ; Clear rdx to avoid issues with imul
imul rdx ; Multiply index by 8
mov rdi, qword [array + rax]

对于基于 index 变量 [0,3] 的读写,最好使用缩放索引寻址模式,而不是单独乘以 8:

movzx ecx, byte [index]      ; Load RCX with index [0,3]
mov   rdi, [array + rcx * 8]

  lea rbx, [allocString]
translateLoop:
  mov dl, [rax]
  mov [rbx], dl
  inc rax
  inc rbx
  cmp byte[rax], 0x0
  jne translateLoop
  mov rax, 8
  movzx rdx, byte [index]
  imul rdx
  mov qword [array + rax], rbx   ; (*)

这里有一些错误:

  • 您希望源字符串永远不会为空
  • 您不复制零终止符,因此目标字符串不会以零终止
  • 当 RBX 指向新字符串的末尾时,您错误地 (*) 将 RBX 复制到指针数组,换句话说:在复制循环中使用它之前存储 RBX。
call stringEdit ; -> RAX lea rbx, [rel allocString] movzx ecx, byte [index] ; Load RCX with index [0,3] mov [array + rcx * 8], rbx copyLoop: movzx edx, byte [rax] mov [rbx], dl inc rax inc rbx cmp byte [rax - 1], 0 jne copyLoop

如果使用 print 函数输出字符串,它将是空白的(例如,它不会输出任何内容)。

(*) 当地址指向字符串后面时就是您所期望的。

© www.soinside.com 2019 - 2024. All rights reserved.