我是装配新手,我正在尝试制作一个最高可达10,000的程序并退出。我正在使用fasm`
include 'include/win32ax.inc'
.data
inchar DB ?
numwritten DD ?
numread DD ?
outhandle DD ?
inhandle DD ?
strFormat DB "Number %d ",0
strBuff RB 64
.code
start:
;set up console
invoke AllocConsole
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov [outhandle],eax
invoke GetStdHandle,STD_INPUT_HANDLE
mov [inhandle],eax
;loop starts here
mov eax, 0
LoopStart:
add eax,1
invoke wsprintf, strBuff, strFormat, eax ;convert number to String.
;the number eax is now in string form in strBuff
;find out the string length of strBuff
mov ecx,-1
mov al,0
mov edi,strBuff
cld
repne scasb
not ecx
dec ecx
;ecx is now the length.
invoke WriteConsole,[outhandle],strBuff,ecx,numwritten,0 ;write to console
;loop
cmp eax, 10000;loop compare
jne LoopStart;jump to start of loop
invoke ReadConsole,[inhandle],inchar,1,numread,0 ;give the user a chance to read console output before exit
invoke ExitProcess,0
.end start `
它应该打印1号2号码3等,但它打印数字2号码2号码2号码2号码等一段时间然后退出,而不等待用户输入。我的代码出了什么问题?
编辑:我开始工作了!工作代码:
include 'include/win32ax.inc'
.data
inchar DB ?
numwritten DD ?
numread DD ?
outhandle DD ?
inhandle DD ?
strFormat DB "Number %d ",0
strBuff RB 64
number DD ?
.code
start:
;set up console
invoke AllocConsole
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov [outhandle],eax
invoke GetStdHandle,STD_INPUT_HANDLE
mov [inhandle],eax
;loop starts here
mov eax, 0
LoopStart:
add eax,1
mov [number],eax
mov edi, eax
push eax
invoke wsprintf, strBuff, strFormat, edi ;convert number to String.
add esp, 4 * 3
pop eax
;the number eax is now in string form in strBuff
;find out the string length of strBuff
mov ecx,-1
mov al,0
mov edi,strBuff
cld
repne scasb
not ecx
dec ecx
;ecx is now the length.
push eax
invoke WriteConsole,[outhandle],strBuff,ecx,numwritten,0 ;write to console
pop eax
;loop
mov eax, [number]
cmp eax, 10000;loop compare
jne LoopStart;jump to start of loop
invoke ReadConsole,[inhandle],inchar,1,numread,0 ;give the user a chance to read console output before exit
invoke ExitProcess,0
.end start
答案 0 :(得分:3)
库函数根据自己的需要使用寄存器,不会将它们恢复为原始值。如果你不想丢失它,你需要在内存中保持价值。最简单的方法是使用stack:
push eax ; put value of eax on the top of stack
pop eax ; remove value from top of stack, save it in eax.
答案 1 :(得分:1)
在调用wsprintf
之后,您无需查找字符串的长度,因为它返回复制到缓冲区的字符数。
接下来,有一个名为Application binary interface (ABI)的内容涵盖了许多细节,例如Calling Conventions
当您处理Windows API或C运行时时,他们会遵循这些调用约定,其中esi
,edi
,ebx
,ebp
和{{ 1}}在函数调用中保存。这意味着,如果你在其中一个寄存器中有一个值,然后调用一个API函数,那么该值在调用后仍然是相同的。
esp
,eax
和ecx
,因此在通话之前您在这些寄存器中拥有的任何内容都不保证是相同的。如果您在这些寄存器中有某些内容,并且在调用后需要该值,则需要使用edx
push
用于返回值。
话虽如此,在此示例中,我使用eax
作为循环计数器,并使用ebx
作为要打印的当前数字,因为这些值将在API调用中保持不变。
这是NASM,但它会给你和想法。
esi