gpt4 book ai didi

assembly - NASM:通过寄存器从内存移动到内存

转载 作者:行者123 更新时间:2023-12-01 23:16:48 29 4
gpt4 key购买 nike

我很难将数据从内存移动到 bss 中的另一个内存。然而,当移动前几个字节中出现一些奇怪的字符时,我的实现在某种程度上有效,并且我的字符串的一半也丢失了,而另一半则很好。

这是我打印出message时得到的值 == �F@elcome to the new life

我需要所有帮助,我缺少什么?我把代码检查了一百遍。

    section .data
hello: db "Hello, Welcome to the new life! Lets begin the journey.",10
hello_len: equ $ - hello

section .bss
message: resb 255

section .text

mov rdi, hello
mov rsi, message

msg_into_message:
cmp byte [rdi], 10 ; hello ends with a new line char
je end_count
mov al, byte [rdi]
mov byte [rsi], al
inc rsi
inc rdi
jmp msg_into_message

end_count:
mov [message], rsi
ret

; Prints message
mov rsi, message
mov rdx, hello_len
call pre_print
syscall

最佳答案

好的,首先,rsirdi 中的 sd 代表 目的地。可能以另一种方式工作(正如你所拥有的那样),但你会让很多像我这样的 CDO 人感到不安( a):-)

但是,对于您的实际问题,请查看此处:

end_count:
mov [message], rsi

假设这意味着将最后一个字节0x10复制到目标中,但有两个问题:

  1. message 是缓冲区的开始,而不是字节应该到达的位置。
  2. 您正在将多字节 rsi 变量复制到其中,而不是您需要的字节。

这两点意味着您在前几个字节中放入了一些奇怪的值,正如您的症状所暗示的那样。

也许更好的方法如下:

    mov rsi, hello            ; as Gordon Moore intended :-)
mov rdi, message

put_str_into_message:
mov al, byte [rsi] ; get byte, increment src ptr.
inc rsi

mov byte [rdi], al ; put byte, increment dst ptr.
inc rdi

cmp al, 10 ; continue until newline.
jne put_str_into_message

ret
<小时/>

为了完整起见,如果您不想复制换行符(尽管这几乎是您现在所拥有的,只是删除了错误的缓冲区破坏mov ) (b):

put_str_into_message:
mov al, byte [rsi] ; get byte.
cmp al, 10 ; stop before newline.
je stop_str

mov byte [rdi], al ; put byte, increment pointers.
inc rsi
inc rdi

jmp put_str_into_message

stop_str:
ret
<小时/>

(a) CDO是强制症,但字母排列正确:-)

<小时/>

(b) 或者,可以更有效地完成不复制换行循环,同时在底部仍然有一个分支。

一次循环一个字节仍然非常效率低下(x86-64SSE2,它可以让你一次复制和检查16个字节时间)。由于长度是汇编时常量 hello_len,因此您可以使用它来有效地复制宽 block (如果缓冲区大小不是 16 的倍数,则可能需要在最后进行特殊处理),或使用rep movsb

但这展示了一种高效的循环结构,避免了将新的 AL 合并到 RAX 底部的错误依赖,从而允许乱序执行提前运行并更早地“看到”循环退出分支。

strcpy_newline_end:
movzx eax, byte [rsi] ; get byte (without false dependency).
cmp al, 10
je copy_done ; first byte isn't newline, enter loop.

copy_loop: ; do:
mov [rdi], al ; put byte.
inc rsi ; increment both pointers.
inc rdi
movzx eax, byte [rsi] ; get next byte.
cmp al, 10
jne copy_loop ; until you get a newline.

; After falling out of the loop (or jumping here from the top)
; we've loaded but *not* stored the terminating newline

copy_done:
ret

您还应该知道,您可以使用其他技巧来保存循环内的指令,例如相对于另一个字符串寻址一个字符串(使用加载的索引寻址模式,仅递增一个指针)。

但是,我们不会在这里详细介绍它们,因为这可能会使答案变得比需要的更加复杂。

关于assembly - NASM:通过寄存器从内存移动到内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58576125/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com