利用堆栈恢复数组的原始值?

问题描述 投票:0回答:1

我有一个类的作业,它让我们创建一个 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 在给定的上下文中并不重要。我需要每个字符串都是随机内容,随机长度,而不是仅仅建立在前一个字符串上直到它崩溃。

arrays assembly x86 masm
1个回答
0
投票
    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
© www.soinside.com 2019 - 2024. All rights reserved.