1

我想重写一个在 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]

因为我什至不能回答我自己的问题,我想我必须把它放在这里。这个问题已经结束了。不管怎么说,还是要谢谢你!

4

1 回答 1

0

对“使用”指令的误解。需要代码来补偿压入堆栈的寄存器。

mov ebp, esp
add ebp, 12
mov esi, [ebp]
于 2013-10-30T01:26:08.857 回答