在x86汇编中连接两个字符串

5

我目前正在AT&T汇编中完成一项任务,现在我需要将两个字符串连接起来:

message: .asciz "String 1"
before: .asciz "String 2"

我真的不知道如何做这件事或从哪里开始。我已经在互联网上搜索过,但没有找到任何有用的信息。我认为我需要将第二个字符串的字符手动复制到第一个字符串的末尾,但我不确定。能否有人向我解释一下如何做呢?:)

AT&T汇编并不存在,它只是一种不同的语法。我猜你可能是指x86汇编? :) - BlackBear
好的,我已经擅自编辑了你的问题 :) - BlackBear
2个回答

7
这个问题没有提到目标内存,这使得回答有些困难。我也不知道你是在16位、32位还是64位环境下。为了方便起见,我假设它们都是C风格的0结尾字符串。
总之,这似乎是一般的过程:
  • 获取第一个字符串的长度(编写汇编strlen指令的说明可以在此处找到:http://www.int80h.org/strlen/
  • 将指针设置为目标内存
  • 使用rep(e/ne) movsb和ecx中的大小将第一个字符串复制到目标内存中。
这可以通过使用'movsd'进行CPU优化,方法是首先对长度进行shr ecx, 2操作,以批量处理4个字节,然后使用movsb处理剩余部分。我看到过像这样的实现:
mov     edi, dest
mov     esi, string_address
mov     ecx, string_length
mov     eax, ecx
shr     ecx, 2
repne movsd
mov     cl, al
and     cl, 3
repne movsb ; esi and edi move along the addresses as they copy, meaning they are already set correctly here
  • 获取第二个字符串的长度(确保如有必要,将edi备份到堆栈或另一个寄存器中,因为它包含了你需要复制下一个字符串的地址)
  • 将第二个字符串复制到目标内存中(如上所述,在第一个字符串操作后,正确的地址应该在edi中)
  • 为了安全起见,在其后面添加一个新的 0。

如果要将第二个字符串复制到第一个字符串的末尾,则需要少进行一次复制操作,但是必须确保有足够的空间来复制第二个字符串而不会覆盖其他重要内容。


2
这不是一个琐碎的问题。字符串长度可变且占用内存中不同的空间,必须有某种方法来知道它们的长度或结束位置。在C或C++中,nul字节(值为零的字节)表示字符串的结尾。在其他一些编程语言中,您有一个指向字符串开头的指针和单独存储的字符串长度,这样可以让您在字符串中存储二进制(包括值为零的字节),这是一个优点。即使对于C和其他语言,您也必须有一个指向字符串开始位置的指针。
通常需要使用汇编语言与操作系统联系,并请求一个当前空闲的足以容纳两个字符串内容的块内存。这将是起始时与任何一个字符串分开的内存块,并且它来自所谓的内存堆。一旦获得该内存块的起始点,您就将第一个字符串的内容复制到其中,然后继续进行,同时将第二个字符串的内容复制到其后面。然后,释放已分配给第一个字符串的内存,并通过更改其指针(可能还有其长度)将该块重新分配给该字符串。被释放的内存由操作系统返回到内存堆以供其他地方重用。
实际上,操作系统并不是唯一的空闲内存来源。一些编译器,甚至汇编程序,要么自己处理内存管理,要么为程序员提供适当的工具以在需要时进行管理。
换句话说,这可能是一个非常有雄心壮志的任务,您必须对正在发生的事情有相当多的了解才能正确地完成它。如果做错了,您可能会遇到像系统崩溃并需要重新启动之类的后果。

1
不确定如何通过执行连接字符串的程序来崩溃您的系统。 - Simon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接