我想重写一个在 MASM615 中给我的程序。我只是打算使用“USES”指令,这样我就不必执行所有进出堆栈的推送和弹出操作。这显然会改变过程中引用的一些地址,因为它们引用堆栈指针(esp)。我以为我正确地实施了它,但程序挂在我身上。该过程应该输出一个直接写入代码流中的字符串,然后跳过该字符串,以便 CPU 不会因为尝试将字符串作为代码执行而出错。以下是我被给予的程序:
WritePrompt PROC
push ebp
mov ebp, esp ; set up the ebp pointer
push esi ; save used reg
push eax ; save used reg
mov esi, [ebp+4] ; use ret.addr. as string pointer
L1: cmp BYTE PTR [esi], 0 ; check for the end of string
jz L2 ; jump if the string is over
mov al, [esi] ; get the next string character
call WriteChar ; ... and output it
inc esi ; increment the string pointer
jmp L1
L2: inc esi ; adjust the string pointer
mov [ebp+4], esi ; modify the return address
pop eax ; restore all used regs and exit
pop esi
pop ebp
ret
WritePrompt ENDP
这就是我得到的,下面是我的简化重写,使用USES指令跳过堆栈推送和弹出:
outStr PROC USES eax ebp esi
mov ebp, esp
mov esi, [ebp]
L1:
cmp BYTE PTR [esi], 0
jz L2
mov al, [esi]
call WriteChar
inc esi
jmp L1
L2:
inc esi
mov [ebp], esi
ret
outStr ENDP
此过程在调用时会导致程序挂起。为什么?它出什么问题了?我觉得我解释了推动和弹出会做出的任何改变。
编辑:在添加“call dumpregs”几个地方进行调试后,我发现导致程序崩溃的行是“cmp BYTE PTR [esi],0”,这让我觉得我没有从堆栈中正确获取指向字符串的指针. 使用“mov esi,[ebp + 4]”似乎至少能让我走得更远,但它会立即跳转到 L2。
编辑2:
我发现了问题。似乎我正在使用的文档对USES指令的作用非常不清楚。它将所有“已使用”寄存器推入堆栈,然后将它们弹出,就像没有使用指令一样。因此,我需要使用的命令是:
mov ebp, esp
add ebp, 12
mov esi, [ebp]
因为我什至不能回答我自己的问题,我想我必须把它放在这里。这个问题已经结束了。不管怎么说,还是要谢谢你!