【发布时间】:2022-01-21 05:56:05
【问题描述】:
我在 Windows 10 64 位机器上用 nasm 编写了以下程序
extern _GetStdHandle@4
extern _WriteFile@20
extern _ReadFile@20
extern _ExitProcess@4
;ReadBufferSize
%define rbs 100
section .rodata
w: dd 3
h: dd 3
text: db "abc", 10
section .data
x: dd 4
y: dd 4
section .bss
stdout: resb 4
stdin: resb 4
readbuff: resb (rbs+2); allow for CR, LF
bytecnt: resb 4
section .text
_print:
push ebp
mov ebp, esp
push 0
lea eax, [ebp-4]
push eax
mov eax, [ebp+8]
push dword [eax]
push dword [ebp+12]
push dword [stdout]
call _WriteFile@20
mov esp, ebp
pop ebp
ret 8
_read:
push ebp
mov ebp, esp
push 0
push dword [ebp+8]
push rbs
push dword [ebp+12]
push dword [stdin]
call _ReadFile@20
sub dword [bytecnt], 2; remove CR and LF
mov esp, ebp
pop ebp
ret 8
_draw:
push ebp
mov ebp, esp
push dword [w]
L1:
push dword [h]
L2:
push text
push x
call _print
dec dword [ebp-8]
cmp dword [ebp-8], 0
jg L2
dec dword [ebp-4]
cmp dword [ebp-4], 0
jg L1
mov esp, ebp
pop ebp
ret
global _main
_main:
push -11
call _GetStdHandle@4 ;Get Stdout handle
mov [stdout], eax
push -10
call _GetStdHandle@4 ;Get Stdin handle
mov [stdin], eax
call _draw
push 0
call _ExitProcess@4
hlt
我会清理它,但这可能会影响某些事情,所以我不会(抱歉)。 _draw 函数应该在屏幕上输出 "abc\n" 9 (3*3) (3 和 3,因为 w 和 h 是 3) 次,但它只输出 5 次。据我检查,_print 按预期工作。如果有帮助,这是我的构建脚本:
@echo off
IF "%~2" EQU "" set f0rm4t=win32
IF "%~2" NEQ "" set f0rm4t=%~2
if exist %1.exe rm %1.exe
if exist %1.obj rm %1.obj
nasm -f %f0rm4t% %1.asm
if exist %1.exe goto run
if not exist %1.obj goto end
gcc %1.obj -o %1.exe
if %errorlevel% EQU 0 goto run
:run
%1.exe
echo ------------------------
if %errorlevel% EQU -1073741819 (
echo exited with C0000005
goto end
)
if %errorlevel% EQU 0 (
echo exited successfully
goto end
)
echo exited with return value %errorlevel%
:end
我使用build filename 命令构建,它可以正常运行。
我检查了我的逻辑,它看起来很好,所以它与嵌套循环有关,我不知道究竟是什么。
完成build命令输出:
C:\Users\User\files>build filename
abc
abc
abc
abc
abc
------------------------
exited successfully
C:\Users\User\files>
如果循环正常工作,则不可能得到 5 次输出,因为它应该是(外部循环的重复)*(内部循环的重复),但 5 是质数。我想不通,所以我把它留给了这个社区。祝您有美好的一天,提前致谢!
【问题讨论】:
-
您的
_draw函数推送但从不弹出,因此堆栈中充满了垃圾,而不是您想象的循环控制变量。 -
@ErikEidt: 嗯,循环控制变量是通过
ebp引用的,所以这些不受推送的影响,但你是对的,w和h的推送是正确的在这里似乎没有任何用处。 -
@500-InternalServerError 、
w和h是在section .rodata中声明的常量,我不想将它们用于循环控制变量
标签: windows assembly nasm nested-loops stack-memory