【问题标题】:Memmove in Assembly汇编中的 Memmove
【发布时间】:2019-05-04 00:37:47
【问题描述】:

我正在尝试将这个 Memmove C 代码组装起来,但没有得到预期的结果。

我在 xubuntu 上使用 x86-64 程序集,调试了 2 小时后,我看不出我哪里错了。

C memmove 代码:

#include <stdio.h> 

extern void * memmove(void *dest, void *src, size_t n);

int main () { 
  char str1[] = "Geeks";  // Array of size 6
  char str2[] = "Quiz";   // Array of size 5 

  puts("str1 before memmove "); 
  puts(str1); 

  /* Copies contents of str2 to sr1 */
  memmove(str1, str2, sizeof(str2));

  puts("\nstr1 after memmove "); 
  puts(str1); 

  return 0; 
} 
/*

void * memmove(void *dest, void *src, size_t n) { 

    char *d = (char *) dest; 
    char *s = (char *) src; 

    if(s == d)
        return dest;

    if(s < d) { 
        //copy from back 
        s=s+n-1; 
        d=d+n-1; 
        while(n--) { 
            *d-- = *s--; 
        } 
    } 
    else { 
        //copy from front 
        while(n--) 
            *d++ = *s++; 
    } 
    return dest; 
} */

汇编代码:

.globl memmove

# RDI = dest
# RSI = src
# RDX = n

# R8 = d
# R9 = s

memmove:
    mov     %rdi, %r8       # d = dest
    mov     %rsi, %r9       # s = src
    jmp     if_equal

if_equal:
    cmp     %r8, %r9        # s == d
    jz      retDest
    ja      else            # s > d
    jb      if_s_minor      # s < d

if_s_minor:
    add     %rdx, %r9       # s = s + n
    sub     $1, %r9         # s = s - 1

    add     %rdx, %r8       # d = d + n
    sub     $1, %r8         # d = d - 1

    jmp     while1

while1:
    cmp     $0, %rdx        # n > 0 ?
    jna     retDest         # if n <= 0 go to retDest
    sub     $1, %rdx        # n--

    movb    (%rsi), %cl     # *dst-- = *src--
    movb    %cl, (%rdi) 

    leaq    -1(%r8), %r8    # *d--
    leaq    -1(%r9), %r9    # *s--
    jmp     while1

else:
    jmp     while2

while2:
    cmp     $0, %rdx        # n > 0 ?
    jna     retDest
    sub     $1, %rdx        # n--

    movb    (%rsi), %cl     # *dst = *src
    movb    %cl, (%rdi) 

    leaq    1(%r8), %r8 # *d++
    leaq    1(%r9), %r9 # *s++
    jmp     while2

retDest:
    mov     %rdi, %rax
    ret

.end

本应在第二张打印件上显示“测验”,但它显示如下:

str1 在 memmove 之前 极客

在 memmove 之后的 str1 极客

【问题讨论】:

  • char str1[] = "Geeks"; // Array of size 100 - 不。 && 我不知道memove() 是什么。你的意思是memmove()
  • 是的,大小为 100 的数组是错误的。我放错了评论。是的,我是 memmove(),我改变了它,因为我以前在同一个文件上有一个 memmove 函数。
  • 已编辑帖子
  • 你在乎这里的效率吗?一次复制 1 个字节与使用 movups 一次复制 16 个字节相比非常慢。 (x86-64 保证 SSE2 可用)。或者更好的 AVX,或者 rep movsb 如果 AVX 不可用。看看 glibc 的 memcpy 实现就是一个很好的例子。 code.woboq.org/userspace/glibc/sysdeps/x86_64/multiarch/…(glibc memcpy 只使用 memmove。)
  • 这是我大学的“家庭作业”,如果可能的话,我应该一直移动 8 个字节,但这并不总是可行的。顺便说一句,那个链接里有很多我不能用的东西。

标签: c assembly x86-64 memmove


【解决方案1】:
movb    (%rsi), %cl     # *dst = *src
movb    %cl, (%rdi) 
leaq    1(%r8), %r8 # *d++
leaq    1(%r9), %r9 # *s++
jmp     while2

这里的问题是您的代码更改了%r8%r9 寄存器,但实际移动中使用的%rdi%rsi 寄存器保持不变,因此一次又一次地重复复制同一个字节!

while1 代码中当然有同样的问题。

【讨论】:

  • sizeof(str2) 返回 5
猜你喜欢
  • 1970-01-01
  • 2021-07-16
  • 2017-08-19
  • 1970-01-01
  • 2010-11-13
  • 2021-04-14
  • 2011-04-04
  • 1970-01-01
  • 2023-03-24
相关资源
最近更新 更多