Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 程序集x86:LEA和MOVSB是否更改我的源字符串?_String_Assembly_X86_Nasm - Fatal编程技术网

String 程序集x86:LEA和MOVSB是否更改我的源字符串?

String 程序集x86:LEA和MOVSB是否更改我的源字符串?,string,assembly,x86,nasm,String,Assembly,X86,Nasm,我正在用汇编程序x86(Windows中的英特尔32位)编写一个程序。我正在做一个程序(用于家庭作业),在这个程序中我必须对字符串进行加密,我将用两个字符组成的块进行迭代。我使用EBX移动源字符串,将其增加2。现在,我没有进入程序的密码部分,因为我遇到了比这更小的问题。问题是,当一个块有相同的字符时,比如“AA”,它不需要经过加密过程,所以我必须按原样将“AA”复制到结果字符串中。我就是这样做的: CypheLoop: call VerifyBlock cmp byte[caracblock],

我正在用汇编程序x86(Windows中的英特尔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”。我使用_get获取源字符串。我试图给出尽可能多的解释和细节,我甚至不能理解它出错的原因。

您使用的
获取
并且缓冲区只有4个字节长(
resd 1
),而您使它们溢出。

当字符串为4个输入字符或更长时,终止的
0
字节在缓冲区之外。(
获取
总共存储5个字节:数据加上一个终止符。4个
'a'
字节放入
源字符串:resd 1
,终止的
0
结果字符串:resd 1
的第一个字节

如果它们相邻,则将src的前2个字节复制到dst会覆盖src的
0
字节,因为它也是dst的第一个字节

使用(大得多的)缓冲区,和/或使用以读取字节数为上限的函数(缓冲区大小)


如何调试: 一旦您知道某个字节正在更改,而您希望它不会更改,请在调试器中对该地址设置一个监视点。然后它将在更改它的指令处停止

在您的例子中,这将是
“AABB”
末尾的终止
0
字节。地址是
sourcestring+4
,因为它位于4个ASCII字节之后。然后让它运行,您将看到它在
rep movsb
处停止

此外,在执行此操作时,您可能会注意到缓冲区只有4字节长,因此
sourcestring+4
位于4字节缓冲区之外,和/或地址与
resultstring
的地址相同


守则检讨:

movesi,0
是无用的;您已经使用
lea
覆盖了EDI。另外,使用
rep movsb
进行固定大小的2字节拷贝也非常复杂

    movzx eax,  word [sourcestring + ebx]      ; 2-byte load
    mov   [resultstring + ebx], ax             ; 2-byte store

或者,如果您坚持使用
movs
,请使用
movsw
一次。(不要
rep movsw
,这样您就不必设置ECX)。

可能源字符串和结果字符串重叠。您是否只为
db 0
或其他内容保留了1字节的空间?查看LEA后面的指针值,以确保
绝对值(EDI-ESI)>=ECX
,否则您的副本会重叠。(无关:
movesi,0
无效,您已经在用
lea
覆盖旧值)我将.bss中的两个字符串声明为resd 1。我注意到,最终,如果这是您的代码块的一部分,则会更容易查看。对此,我很抱歉,我是该站点的新用户,并且我仍然在尝试,在编程方面还不是很专业。我按照您的要求做了。没关系,EDI-ESI>=ECX。您不必是专家在编程时,你可以问一个问题,但你必须从读者的角度来思考。试着让你的示例代码块自包含。