c - 如何在汇编中实现 memmove,而不仅仅是 memcpy?
问题描述
我试图将 memmove 从 C 实现到 x86 程序集,所以我写道:
start:
movb source(%eax), %cl
movb %cl, destination(%eax)
inc %eax
cmp num, %eax
jne start
end:
但这是错误的,为什么呢?根据:http ://www.cplusplus.com/reference/cstring/memmove/
将 num 个字节的值从 source 指向的位置复制到 destination 指向的内存块。复制就像使用了中间缓冲区一样进行,允许目标和源重叠。
我的代码不支持。
如何在不使用堆栈的情况下解决此问题? 注意:我们可以假设在源目标进入内存之后,num(要复制的字节数)很远并且不能被错误触及。
解决方案
这里的问题是关于潜在的重叠情况destination - source < size
(即两者都source
指向destination
同一个数据块)。发生这种情况时,您将处于以下情况:
AAAAAAAAAAAAAABBBBBBBBBBBBBB_______________________
^ ^ ^ ^
source destination source destination
+ num + num
如果您从 开始复制source
,您将覆盖您尝试复制的部分内容(在此示例中,您将B
用s 覆盖A
s),丢失原始值,最终结果如下:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_________
^ ^ ^ ^
source destination source destination
+ num + num
在现实中你想要这个:
AAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBB_________
^ ^ ^ ^
source destination source destination
+ num + num
destination - source < num
您可以通过检查 when并在这种情况下反向复制(以 开头)来解决此问题eax = num
。
相应的程序集将是这样的:
mov $destination, %eax
sub $source, %eax # dst-src distance in bytes
cmp num, %eax
jb backwards # if (dst-src < copy_size) goto backwards
forward:
mov $0, %eax
forward_loop:
movb source(%eax), %cl
movb %cl, destination(%eax)
inc %eax
cmp num, %eax
jne forward_loop
jmp end
backwards:
movl num, %eax # start from i=length
backwards_loop:
movb source-1(%eax), %cl
movb %cl, destination-1(%eax)
dec %eax
jnz backwards_loop
end:
推荐阅读
- sqoop - Sqoop 导入问题(排除操作)
- javascript - 使用 Node 和 FS 制作我自己的“数据库”
- java - 特定视图的手势检测
- vim - VIM:omnicomplete 弹出菜单有不完整的消息
- javascript - 使用 fetch() 时在 mozilla firefox 中阻止跨源请求
- node.js - 需要为类别和子类别创建api(-使用反向关系)
- android-studio - android studio 设备配置文件
- javascript - 使用 p5.js 制作画布
- php - 使用 img src= 时隐藏 .mp4 不显示
- html - CSS 定位和列表项的问题