我有一个类的作业,它让我们创建一个 CreateRandomString proc,它将创建不同值的字符串,并且每次都将它们存储在 arrayString 中。然后在 main proc 中,writeLoop 将遍历每个字符串 20 次,总共 20 个字符串。每个字符串的长度和内容都是随机的,但都必须是大写字母。我的程序成功运行,除了由于我正在使用的很多东西的全局性质而导致 arrayString 没有正确重置这一事实。我确定我可以以某种方式利用堆栈,但我不太确定如何。能否以某种方式推送数组的一些已清除版本,然后在需要生成新字符串时将其弹出?我真的对我在这里所缺少的东西感到茫然。我对装配还很陌生,非常希望得到任何人在这个问题上的任何建议或指示,或者更好的方法来解决这个问题。我还想指出,我使用了 Irvine32 库中的一个名为 RandomRange 的过程,它只是采用 EAX 值 100 并从 0-(100-1) 中滚动一个随机值。
;.386
;.model flat,stdcall
;.stack 4096
;ExitProcess proto,dwExitCode:dword
INCLUDE Irvine32.inc
.data
arrayString BYTE 100 DUP (?)
mainLoopCounter DWORD 20
.code
CreateRandomString proc
mov ESI, OFFSET arrayString
mov ECX, EAX ;Length of string
storeLoop:
mov EAX, 26
call RandomRange
add EAX, 65
mov BYTE PTR [ESI], AL
inc esi
loop storeLoop
call CRLF
ret
CreateRandomString endp
main proc
call Randomize
mainL:
mov EAX, 100
call RandomRange
call CreateRandomString
mov ESI, OFFSET arrayString
mov ECX, LENGTHOF arrayString
writeLoop:
mov AL, BYTE PTR [ESI]
call WriteChar
inc ESI
loop writeLoop
mov ECX, mainLoopCounter
dec mainLoopCounter
loop mainL
Invoke ExitProcess,0
main endp
end main
就我尝试解决问题的方法而言,我一直在篡改堆栈,因为这是我们学到的将事物恢复为原始值的一种方法。由于 ECX 和 ESI 在程序的其他部分被篡改,因此在我的 storeLoop 开始时,我确实推送了 ESI 并推送了 ECX,然后在 storeLoop 结束后按各自的顺序弹出它们完全无济于事。我认为这是因为 ESI 实际上只是一个地址,用于存储生成的 char 并不断增加和变化,而 ECX 在给定的上下文中并不重要。我需要每个字符串都是随机内容,随机长度,而不是仅仅建立在前一个字符串上直到它崩溃。
mov ESI, OFFSET arrayString mov ECX, LENGTHOF arrayString writeLoop:
不要用
LENGTHOF arrayString
初始化计数器。您需要使用与 CreateRandomString: 相同的编号设置 ECX
mov EAX, 100
call RandomRange ; -> EAX
push eax ; (1)
call CreateRandomString
pop ecx ; (1)
mov ESI, OFFSET arrayString
writeLoop:
您的 RandomRange 可以在 EAX 中返回一个从 0 到 99 的数字。当输入零时,CreateRandomString 过程将无法正常运行!最好永远不要将零传递给此过程:
Redo:
mov EAX, 100
call RandomRange ; -> EAX
test eax, eax
jz ReDo
push eax ; (1) [1,99]
call CreateRandomString
pop ecx ; (1)
mov ESI, OFFSET arrayString
writeLoop:
loop
指令!mov ECX, mainLoopCounter dec mainLoopCounter loop mainL
这可以写得更简单并且执行得更快:
dec mainLoopCounter
jnz mainL