assembly x86 64位程序集,从函数返回字符串并将其放入数组

ff29svar  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(55)

我使用的是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被解引用,这将导致在打印时出现seg错误,如果没有引用,任何其他时候调用函数,数组中的所有内容都指向同一个东西,因此,任何调用此函数的数组索引将共享相同的结果。

call stringEdit

mov qword [array + rax], rdi ;;moved it to the rdi before

rdrgkggo

rdrgkggo1#

我试过

returnString:
    mov rax, [newString]
    ret

字符串
这将返回新字符串内容的前8个字节。您的第一次尝试是正确的,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


can't move a 64-bit immediate to memory和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


Info about RIP relative addressing的一个。

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之前存储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函数输出字符串,则它将为空(例如,它将不输出任何内容)。
(*)是当地址指向字符串后面时所期望的值。

相关问题