我尝试调用 Win32 API WriteConsoleOutputA 使用 NASM
I Try Call Win32 API WriteConsoleOutputA use NASM
我尝试调用 WriteConsoleOutputA 使用 NASM
但是错误信息总是显示
87 (0x57)
参数不正确
我不知道如何解决这个问题
STD_OUTPUT_HANDLE EQU -11
NULL EQU 0
GLOBAL GobleyGook
EXTERN ExitProcess, GetLastError, GetStdHandle, WriteConsoleA, WriteConsoleOutputA, FormatMessageA
SECTION .data
STRUC lpBuffer
.Char : RESW 1
.Attributes: RESD 1
ENDSTRUC
_lpBuffer ISTRUC lpBuffer
at lpBuffer.Char, DW 'A'
at lpBuffer.Attributes, DD 1H
IEND
STRUC dwBufferSize
.X: RESW 1
.Y: RESW 1
ENDSTRUC
_dwBufferSize ISTRUC dwBufferSize
at dwBufferSize.X, DW 10
at dwBufferSize.Y, DW 10
IEND
STRUC dwBufferCoord
.X: RESW 1
.Y: RESW 1
ENDSTRUC
_dwBufferCoord ISTRUC dwBufferCoord
at dwBufferCoord.X, DW 0
at dwBufferCoord.Y, DW 0
IEND
STRUC smallRect
.Left : RESW 1
.Top : RESW 1
.Right : RESW 1
.Bottom: RESW 1
ENDSTRUC
_smallRect ISTRUC smallRect
IEND
SECTION .bss
dummy RESD 1
err RESD 1
err2 RESD 1
SECTION .text
GobleyGook:
PUSH STD_OUTPUT_HANDLE
CALL GetStdHandle
PUSH _smallRect
PUSH _dwBufferCoord
PUSH _dwBufferSize
PUSH _lpBuffer
PUSH EAX
CALL WriteConsoleOutputA
CALL GetLastError
PUSH NULL
PUSH 99
PUSH err
PUSH NULL
PUSH EAX
PUSH NULL
PUSH 1000H
CALL FormatMessageA
PUSH STD_OUTPUT_HANDLE
CALL GetStdHandle
push NULL
push dummy
push 32
push err
push EAX
call WriteConsoleA
PUSH NULL
CALL ExitProcess
Link & 编译器
nasm -f win32 print.asm
golink.exe /console /entry GobleyGook print.obj kernel32.dll
在 windows 8.1 64 位
API 文档
https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms687404(v=vs.85).aspx
请帮帮我....
只需按如下方式修改您的代码即可!
PUSH STD_OUTPUT_HANDLE
CALL GetStdHandle
PUSH _smallRect
mov ecx, [_dwBufferCoord]
PUSH ecx
mov edx, [_dwBufferSize]
PUSH edx
PUSH _lpBuffer
PUSH EAX
CALL WriteConsoleOutputA
你的代码有几个错误:
- 正如评论中指出的,您需要按值传递
COORD
参数
- 您需要传递一个等于缓冲区大小的
dwBufferSize
值
- 您需要传递一个
lpWriteRegion
结构(通过引用),该结构使用您希望缓冲区在屏幕上显示的位置的坐标进行初始化。
- 您需要检查
WriteConsoleOutputA
的return值来判断是否失败。您不能可靠地使用 GetLastError
来确定它是否失败。
- 您对
lpBuffer
结构的定义不正确。相应 CHAR_INFO
结构的第二个成员 Attributes
是 16 位 WORD
而不是 32 位 DWORD
.
您的缓冲区只有一个字符,使其成为 1x1 缓冲区,但您正试图传递 10x10 大小的缓冲区。因为你没有初始化 _smallRect
它的值是 0,0,0,0 将输出放在控制台缓冲区的左上角。这意味着您的单字符输出可能会在您的程序完成并打印命令提示符时立即滚出屏幕,您将永远看不到它。
这是修复了所有这些问题的程序版本:
STD_OUTPUT_HANDLE EQU -11
NULL EQU 0
GLOBAL GobleyGook
EXTERN _ExitProcess@4, _GetLastError@0, _GetStdHandle@4, _WriteConsoleA@20, _WriteConsoleOutputA@20, _FormatMessageA@28
SECTION .data
STRUC lpBuffer
.Char : RESW 1
.Attributes: RESW 1
ENDSTRUC
_lpBuffer ISTRUC lpBuffer
at lpBuffer.Char, DW 'A'
at lpBuffer.Attributes, DW 2H | 8H
IEND
STRUC smallRect
.Left : RESW 1
.Top : RESW 1
.Right : RESW 1
.Bottom: RESW 1
ENDSTRUC
_smallRect ISTRUC smallRect
at smallRect.Left, DW 40
at smallRect.Top, DW 12
at smallRect.Right, DW 41
at smallRect.Bottom, DW 13
IEND
SECTION .bss
dummy RESD 1
err RESD 1
err2 RESD 1
SECTION .text
GobleyGook:
PUSH STD_OUTPUT_HANDLE
CALL _GetStdHandle@4
PUSH _smallRect
PUSH (0 << 16) | 0 ; dwBufferCoord = 0,0
PUSH (1 << 16) | 1 ; dwBufferSize = 1,1
PUSH _lpBuffer
PUSH EAX
CALL _WriteConsoleOutputA@20
cmp eax, 0
jnz .exit
CALL _GetLastError@0
PUSH NULL
PUSH 99
PUSH err
PUSH NULL
PUSH EAX
PUSH NULL
PUSH 1000H
CALL _FormatMessageA@28
PUSH STD_OUTPUT_HANDLE
CALL _GetStdHandle@4
push NULL
push dummy
push 32
push err
push EAX
call _WriteConsoleA@20
.exit:
PUSH 0
CALL _ExitProcess@4
我已经更改了您的程序,使其在 40,12 处显示单字符缓冲区,并将其设为亮绿色而不是深蓝色,这样它在黑色背景上显示效果更好。我还将 API 函数的名称更改为它们的实际程序集名称,因此它会 link 与 Microsoft linker。
我尝试调用 WriteConsoleOutputA 使用 NASM
但是错误信息总是显示
87 (0x57)
参数不正确
我不知道如何解决这个问题
STD_OUTPUT_HANDLE EQU -11
NULL EQU 0
GLOBAL GobleyGook
EXTERN ExitProcess, GetLastError, GetStdHandle, WriteConsoleA, WriteConsoleOutputA, FormatMessageA
SECTION .data
STRUC lpBuffer
.Char : RESW 1
.Attributes: RESD 1
ENDSTRUC
_lpBuffer ISTRUC lpBuffer
at lpBuffer.Char, DW 'A'
at lpBuffer.Attributes, DD 1H
IEND
STRUC dwBufferSize
.X: RESW 1
.Y: RESW 1
ENDSTRUC
_dwBufferSize ISTRUC dwBufferSize
at dwBufferSize.X, DW 10
at dwBufferSize.Y, DW 10
IEND
STRUC dwBufferCoord
.X: RESW 1
.Y: RESW 1
ENDSTRUC
_dwBufferCoord ISTRUC dwBufferCoord
at dwBufferCoord.X, DW 0
at dwBufferCoord.Y, DW 0
IEND
STRUC smallRect
.Left : RESW 1
.Top : RESW 1
.Right : RESW 1
.Bottom: RESW 1
ENDSTRUC
_smallRect ISTRUC smallRect
IEND
SECTION .bss
dummy RESD 1
err RESD 1
err2 RESD 1
SECTION .text
GobleyGook:
PUSH STD_OUTPUT_HANDLE
CALL GetStdHandle
PUSH _smallRect
PUSH _dwBufferCoord
PUSH _dwBufferSize
PUSH _lpBuffer
PUSH EAX
CALL WriteConsoleOutputA
CALL GetLastError
PUSH NULL
PUSH 99
PUSH err
PUSH NULL
PUSH EAX
PUSH NULL
PUSH 1000H
CALL FormatMessageA
PUSH STD_OUTPUT_HANDLE
CALL GetStdHandle
push NULL
push dummy
push 32
push err
push EAX
call WriteConsoleA
PUSH NULL
CALL ExitProcess
Link & 编译器
nasm -f win32 print.asm
golink.exe /console /entry GobleyGook print.obj kernel32.dll
在 windows 8.1 64 位
API 文档
https://msdn.microsoft.com/zh-tw/library/windows/desktop/ms687404(v=vs.85).aspx
请帮帮我....
只需按如下方式修改您的代码即可!
PUSH STD_OUTPUT_HANDLE
CALL GetStdHandle
PUSH _smallRect
mov ecx, [_dwBufferCoord]
PUSH ecx
mov edx, [_dwBufferSize]
PUSH edx
PUSH _lpBuffer
PUSH EAX
CALL WriteConsoleOutputA
你的代码有几个错误:
- 正如评论中指出的,您需要按值传递
COORD
参数 - 您需要传递一个等于缓冲区大小的
dwBufferSize
值 - 您需要传递一个
lpWriteRegion
结构(通过引用),该结构使用您希望缓冲区在屏幕上显示的位置的坐标进行初始化。 - 您需要检查
WriteConsoleOutputA
的return值来判断是否失败。您不能可靠地使用GetLastError
来确定它是否失败。 - 您对
lpBuffer
结构的定义不正确。相应CHAR_INFO
结构的第二个成员Attributes
是 16 位WORD
而不是 32 位DWORD
.
您的缓冲区只有一个字符,使其成为 1x1 缓冲区,但您正试图传递 10x10 大小的缓冲区。因为你没有初始化 _smallRect
它的值是 0,0,0,0 将输出放在控制台缓冲区的左上角。这意味着您的单字符输出可能会在您的程序完成并打印命令提示符时立即滚出屏幕,您将永远看不到它。
这是修复了所有这些问题的程序版本:
STD_OUTPUT_HANDLE EQU -11
NULL EQU 0
GLOBAL GobleyGook
EXTERN _ExitProcess@4, _GetLastError@0, _GetStdHandle@4, _WriteConsoleA@20, _WriteConsoleOutputA@20, _FormatMessageA@28
SECTION .data
STRUC lpBuffer
.Char : RESW 1
.Attributes: RESW 1
ENDSTRUC
_lpBuffer ISTRUC lpBuffer
at lpBuffer.Char, DW 'A'
at lpBuffer.Attributes, DW 2H | 8H
IEND
STRUC smallRect
.Left : RESW 1
.Top : RESW 1
.Right : RESW 1
.Bottom: RESW 1
ENDSTRUC
_smallRect ISTRUC smallRect
at smallRect.Left, DW 40
at smallRect.Top, DW 12
at smallRect.Right, DW 41
at smallRect.Bottom, DW 13
IEND
SECTION .bss
dummy RESD 1
err RESD 1
err2 RESD 1
SECTION .text
GobleyGook:
PUSH STD_OUTPUT_HANDLE
CALL _GetStdHandle@4
PUSH _smallRect
PUSH (0 << 16) | 0 ; dwBufferCoord = 0,0
PUSH (1 << 16) | 1 ; dwBufferSize = 1,1
PUSH _lpBuffer
PUSH EAX
CALL _WriteConsoleOutputA@20
cmp eax, 0
jnz .exit
CALL _GetLastError@0
PUSH NULL
PUSH 99
PUSH err
PUSH NULL
PUSH EAX
PUSH NULL
PUSH 1000H
CALL _FormatMessageA@28
PUSH STD_OUTPUT_HANDLE
CALL _GetStdHandle@4
push NULL
push dummy
push 32
push err
push EAX
call _WriteConsoleA@20
.exit:
PUSH 0
CALL _ExitProcess@4
我已经更改了您的程序,使其在 40,12 处显示单字符缓冲区,并将其设为亮绿色而不是深蓝色,这样它在黑色背景上显示效果更好。我还将 API 函数的名称更改为它们的实际程序集名称,因此它会 link 与 Microsoft linker。