string - 大会 x86:LEA 和 MOVSB 更改了我的源字符串?
问题描述
我正在使用 Assembler x86(Windows 中的 Intel 32 位)做一个程序。我正在制作一个程序(用于家庭作业),我必须在其中加密一个字符串,我将通过两个字符符合的块对其进行迭代。我使用 EBX 在源字符串中移动,将其增加 2。目前,我没有进入程序的加密部分,因为我遇到了比这更小的问题。问题是,当一个块具有相同的字符时,比如“AA”,它不需要经过密码处理,所以我必须将“AA”原样复制到结果字符串中。这就是我这样做的方式:
CypheLoop:
call VerifyBlock
cmp byte[caracblock], 0
je End
cmp byte[caracblock], 1
je AddLastCharacter
cmp byte[caracblock], 2
je AddNoCiphedBlock
jmp CipheLoop
VerifyBlock 负责查看一个块的一致性,它根据其特征将“caracblock”更改为一个数字。0 表示块为空(表示字符串结束),1 表示块中只有一个字符(例如“ABC”,将有一个只有“C”的块),2 如果块的字符必须按原样复制(如前所述,另一种情况是块中有空格),或者如果块需要加密,则为 3。到目前为止,一切都很好!程序按预期添加字符并完成,但是,AddNoCiphedBlock 有一些意外行为,它看起来像这样:
AddNoCiphedBlock:
mov esi, 0
mov edi, 0
mov ecx, 2
lea esi, [sourcestring + ebx]
lea edi, [resultstring + ebx]
rep movsb
add ebx, 2
jmp CipheLoop
问题不在于它返回什么(尽管我得到的不是我所期望的),但问题的根源在于,由于某种原因,源字符串被改变了。如果我写“AA”,我得到“AA”,正确。如果我写“AABB”,我会得到“AABB”,这是正确的。如果我写“AABBCC”,我会得到“AABBAA”。源字符串,在使用 AddNoCiphedBlock 后,变为“AABBAA”,并且继续恶化。这就是通过该过程对源字符串发生的事情。
AABBCC
AABBAA
AABBAA
AABBAABB
AABBAABB
AABBAABBAA
为什么会这样?我只是从源头复制一些东西!我的源字符串和结果字符串都在 .bss 部分中,分别为“sourcestring resd 1”和“resultstring resd 1”。我使用 _gets 来获取源字符串。我试图给出尽可能多的解释和细节,我什至无法理解为什么会出现这样的错误。
解决方案
您只使用gets
和缓冲了 4 个字节长 ( resd 1
),然后溢出了它们。
当您的字符串为 4 个输入字符或更长时,终止0
字节位于缓冲区之外。(gets
总共存储 5 个字节:数据加上一个终止符。4'A'
个字节进入,sourcestring: resd 1
终止0
是resultstring: resd 1
.
如果它们相邻,则将 src 的前 2 个字节复制到 dst 会覆盖src的0
字节,因为它也是 dst 的第一个字节。
使用(大得多)更大的缓冲区,和/或使用一个函数,该函数采用读取多少字节的上限(缓冲区大小)。
如何调试这个:
一旦您知道一个字节正在更改而您希望不会更改,请在调试器中的该地址上设置一个观察点。然后它将在更改它的指令处停止。
在您的情况下,这将0
是"AABB"
. 该地址是sourcestring+4
因为它位于 4 个 ASCII 字节之后。然后让它运行,你会看到它停在rep movsb
.
此外,您在执行此操作时可能会注意到您的缓冲区只有 4 个字节长,因此sourcestring+4
位于 4 字节缓冲区之外,和/或地址与resultstring
.
代码审查:
mov esi,0
没用;您已经使用lea
. 此外,使用rep movsb
固定大小的 2 字节副本非常复杂。
movzx eax, word [sourcestring + ebx] ; 2-byte load
mov [resultstring + ebx], ax ; 2-byte store
或者,如果您坚持movs
,请使用movsw
一次。(不是rep movsw
这样你就不必设置ECX)。
推荐阅读
- react-native - 与android反应本机错误
- sap - 将 Sap Cloud Platform hana 数据库与 Web-IDE 数据库浏览器连接
- jquery - 在Vue Js for循环中动态调用函数
- java - 获取preparedStatement 的可能数据类型 - Java DB2
- python - 使用 python ZIPFile 提取 gz 文件
- android - 即使 windowNoTitle 为 True,应用程序对话框主题也会显示默认标题
- python - 当我运行脚本时,Python 3.6 不是默认的
- r - 使用 grepl 和 ifelse 进行基于条件的字符串匹配
- r - Shiny:从名称列表中创建一个 reactiveValues
- c# - “指定的 OData 查询具有无效的实际文字”