组装: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 调用约定包括以下规则:
- The volatile registers are: EAX, ECX, EDX, and ST0 - ST7
- The non-volatile registers are: EBX, EBP, ESP, EDI, ESI, CS, DS, ES, FS and GS
这意味着您不能假定 EAX、ECX 和 EDX 在 call
/invoke
之后将保持不变。您的循环变量是 ECX 因此每次调用 StdOut
时调用 ECX 很可能会破坏 ECX 导致无限循环。
最好的选择是使用其中一种非易失性寄存器EBX、EDI、ESI(如果使用 EBP 和 ESP,则会导致其他问题)。如果您 运行 超出寄存器,您可以:
- 在调用
StdOut
之前和之后保存和恢复 ECX 的值,方法与保存 EDX 的方式相同在您的代码中使用 PUSH/POP。
- 将它们存储在全局或基于堆栈的内存位置并在之后恢复它们。
- 编写代码以避免在循环中使用额外的寄存器。
我正在使用 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 调用约定包括以下规则:
- The volatile registers are: EAX, ECX, EDX, and ST0 - ST7
- The non-volatile registers are: EBX, EBP, ESP, EDI, ESI, CS, DS, ES, FS and GS
这意味着您不能假定 EAX、ECX 和 EDX 在 call
/invoke
之后将保持不变。您的循环变量是 ECX 因此每次调用 StdOut
时调用 ECX 很可能会破坏 ECX 导致无限循环。
最好的选择是使用其中一种非易失性寄存器EBX、EDI、ESI(如果使用 EBP 和 ESP,则会导致其他问题)。如果您 运行 超出寄存器,您可以:
- 在调用
StdOut
之前和之后保存和恢复 ECX 的值,方法与保存 EDX 的方式相同在您的代码中使用 PUSH/POP。 - 将它们存储在全局或基于堆栈的内存位置并在之后恢复它们。
- 编写代码以避免在循环中使用额外的寄存器。