assembly 嵌套循环理解+ push/pop

abithluo  于 2023-03-30  发布在  其他
关注(0)|答案(1)|浏览(118)

我试图创建一个过程,生成一个长度为L的随机字符串,包含所有大写字母。此过程接收EAX中的字符串长度(L),以及指向ESI中将保存随机字符串的字节数组的指针。返回指向ESI中保存随机字符串的字节数组的指针。

;.386
;.model flat,stdcall
;.stack 4096
;ExitProcess PROTO, dwExitCode:DWORD
INCLUDE Irvine32.inc

.data
;bArray BYTE 100 DUP(0), 0
bArray BYTE ?
count DWORD ?
ranNum DWORD ?

.code
main proc
    call Clrscr
    mov esi, OFFSET bArray
    call Randomize
    mov ecx, 20
    
L1:
    ;call Random32
    mov count, ecx
    mov eax, 100
    call RandomRange
    inc eax
    mov ranNum, eax
    call CreateRandomString
    loop L1

    invoke ExitProcess,0
main endp

CreateRandomString PROC
; Receives: Length of the string (L) in EAX, the pointer
; to a byte array in ESI where the random string will be saved
; Returns: Pointer to a byte array in ESI held the random string
;-----------------------------------------------------
mov ecx, ranNum
L2:
    mov eax, 26
    call RandomRange
    add eax, 65
    mov[esi], eax
    call WriteChar
    loop L2
    mov ecx, count
call Crlf
ret
CreateRandomString ENDP

end main

这是我的代码,到目前为止,它生成随机长度的字符串,但当我只想让它迭代20次时,循环是无限的。我知道我在ecx中输入的20会丢失,但我不确定在代码中发生了什么,我应该做些什么来改变它。我正在考虑一些与push和pop有关的事情,但我仍然对这个概念感到困惑和困惑。提前谢谢你!

shyt4zoc

shyt4zoc1#

是否故意将字符串中的所有字符都存储在彼此的顶部**?
对于bArray BYTE ?mov esi, OFFSET bArray,随后在 CreateRandomString 过程中 not 递增ESI,这正是将要发生的情况。

为什么会出现无限循环

bArray BYTE ?
count DWORD ?

由于 bArray 被定义为一个字节,您不应该像mov [esi], eax那样向它写入一个完整的双字,而是应该写入mov [esi], al。您实际上已经破坏了存储在 count 变量中的值20(您引入的是一种保留ECX的复杂方法)。因此,主 L1 循环中的loop指令将始终作用于ECX=0,无限循环回去!
我在想和pushpop有关的东西
如果你想在你的 CreateRandomString 过程中再次使用ECX,那么只需将它保存在堆栈上:

CreateRandomString PROC
    push ecx             ; Preserve ECX
    mov  ecx, ranNum
L2: mov  eax, 26
    call RandomRange     ; -> EAX=[0,25]
    add  eax, 65
    mov  [esi], al       ; Currently storing on top of each other due to
    call WriteChar       ;       lack of `inc esi`, for testing no doubt
    loop L2
    call Crlf
    pop  ecx             ; Restore ECX
    ret
CreateRandomString ENDP

正如其他人所建议的,如果你在主 L1 循环中使用另一个计数寄存器,那么在 CreateRandomString 过程中保留和恢复ECX是不必要的。作为奖励,你将避免使用the slow loop instruction

mov  ebx, 20
L1: mov  eax, 100
    call RandomRange     ; -> EAX=[0,99]
    inc  eax
    mov  ranNum, eax
    call CreateRandomString
    dec  ebx
    jnz  L1

相关问题