组装:ecx不减少

Assembly: ecx not decreasing

我正在使用 MASM,目前正在实现一个显示大写字母、小写字母和介于两者之间的 ASCII 的循环

.386

.model flat, stdcall
option casemap :none

include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\include\masm32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\masm32.lib 

.data
    _ret sdword 13
    _car sdword 10
    _num sdword 0


.code
main:
    mov edx, 'A'
    mov ecx, 58
    jmp _end

_loop:  
    push edx
    invoke StdOut, esp
    invoke StdOut, addr _ret
    invoke StdOut, addr _car
    pop edx

    inc edx
    dec ecx

_end:
    cmp ecx, 0
    jne _loop

_exit:    
    invoke ExitProcess, 0
end main

我面临的问题是 ECX 在循环主体期间没有减少,即使在 A-Z %somehere% a-z

之后循环也会永远继续

您的问题与调用约定有关。您已将默认约定设置为 .model flat, stdcall,这不是问题。这意味着除非另有说明,否则 stdcall calling convention 将由 invoke 指令使用。 stdcall 调用约定包括以下规则:

  1. The volatile registers are: EAX, ECX, EDX, and ST0 - ST7
  2. The non-volatile registers are: EBX, EBP, ESP, EDI, ESI, CS, DS, ES, FS and GS

这意味着您不能假定 EAXECXEDXcall/invoke 之后将保持不变。您的循环变量是 ECX 因此每次调用 StdOut 时调用 ECX 很可能会破坏 ECX 导致无限循环。

最好的选择是使用其中一种非易失性寄存器EBXEDIESI(如果使用 EBPESP,则会导致其他问题)。如果您 运行 超出寄存器,您可以:

  • 在调用 StdOut 之前和之后保存和恢复 ECX 的值,方法与保存 EDX 的方式相同在您的代码中使用 PUSH/POP
  • 将它们存储在全局或基于堆栈的内存位置并在之后恢复它们。
  • 编写代码以避免在循环中使用额外的寄存器。