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

r6l8ljro  于 2023-03-23  发布在  其他
关注(0)|答案(1)|浏览(110)

x1c 0d1xI有一个类的任务,让我们创建一个CreateRandomString proc,它将创建不同值的字符串,每次将它们存储在arrayString中。然后在main proc中,writeLoop将迭代每个字符串,总共20个字符串20次。每个字符串的长度和内容都是随机的,但所有字符串都必须是大写字母。我的程序工作得很成功,除了一个事实,即arrayString没有得到正确的重置,由于我使用的很多东西的全局性质。我相信我可以以某种方式利用堆栈,但我不太确定如何。是否可以以某种方式推送数组的某个清除版本,然后在需要生成新字符串时弹出它?我真的不知道我在这里错过了什么。我是相当新的组装和所有的任何建议或指针任何人都在这个问题上或一个更好的方法来处理这个问题。我还想指出的是,我使用了Irvine 32库中的一个名为RandomRange的proc,它只取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在给定的上下文中并不重要。我需要每个字符串具有随机内容,随机长度,而不是仅仅在前一个字符串上构建,直到它崩溃。

0h4hbjxa

0h4hbjxa1#

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:

Something to watch out for

您的 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

相关问题