通过中间函数调用 WriteConsole 无法正常工作
Posted
技术标签:
【中文标题】通过中间函数调用 WriteConsole 无法正常工作【英文标题】:Calling WriteConsole through an intermediate function does not work properly 【发布时间】:2015-12-04 14:35:56 【问题描述】:我正在尝试学习 assembly
,所以我手动将 C
和 C++
代码转换为 assembly
代码。
环境
x86
Visual Studio
目标
手动将以下C
代码转换为assembly
代码:
static HANDLE OUTPUT_HANDLE;
BOOL __stdcall InputConsole(const VOID *lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten)
WriteConsoleA(OUTPUT_HANDLE, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, 0);
int main()
DWORD charsWritten;
OUTPUT_HANDLE = GetStdHandle(STD_OUTPUT_HANDLE);
InputConsole("Hello World!\n", 13, &charsWritten);
尝试
.586
.model flat, stdcall
.stack 4096
EXTRN ExitProcess@4 : PROC
EXTRN GetStdHandle@4 : PROC
EXTRN WriteConsoleA@20 : PROC
.data
STD_OUTPUT_HANDLE DD ?
WRITE_CONSOLE_STRING DB "Hello World!", 10, 0
CHARS_WRITTEN DD ?
.code
WriteConsole PROC
PUSH 0 ; lpReserved
MOV EAX, [ESP + 16] ; lpNumberOfCharsWritten
PUSH EAX
MOV EAX, [ESP + 16] ; nNumberOfCharsToWrite
PUSH EAX
MOV EAX, [ESP + 16] ; lpBuffer
PUSH EAX
PUSH STD_OUTPUT_HANDLE ; hConsoleOutput
CALL WriteConsoleA@20
ADD ESP, 12 ; Restore stack
RET
WriteConsole ENDP
main: NOP
PUSH -11
CALL GetStdHandle@4;
MOV STD_OUTPUT_HANDLE, EAX
LEA EAX, CHARS_WRITTEN
PUSH EAX
PUSH 13
LEA EAX, WRITE_CONSOLE_STRING
PUSH EAX
CALL WriteConsole
PUSH 0
CALL ExitProcess@4
END main
问题
到目前为止,它确实打印了实际行,但是Access Violation Exception
被抛出ADD ESP, 12
。在使用调试器仔细检查后,似乎我应该将 16
而不是 12
添加到 ESP 以恢复堆栈。仍然在创建16
之后,它会在从procedure
返回后冻结应用程序。
问题
我只在堆栈中压入三个 4 字节参数,为什么我需要添加16
而不是 12
?
使用ESP + xx
访问“输入参数”是否正确?
为什么我的程序会冻结,即使我正在恢复堆栈并且控制台上实际写入了一些内容?
是否有另一种方法可以在 assembly
中“通过引用传递参数”而不是使用全局 .data
地址?
旁注
我知道您可以在 Visual Studio(这是我正在使用的 IDE)中为过程设置参数,但是我应该可以这样做,对吧?
【问题讨论】:
WriteConsoleA
将自行从堆栈中删除参数,因此请尝试删除 ADD ESP, 12
。
@MikeCAT 我知道这一点,但我也需要从堆栈中删除为我的自定义过程提供的参数。因为我正在关注 __stdcall
add esp
不能这样做,ret 12
不能这样做。
InputConsole
接受 3 个参数,因此数量为 4 * 3 = 12。RET imm16
指令对于“返回并将 imm16
添加到 ESP
”很有用。
一共是16个,是的,返回地址4个字节,参数12个。但顺序很重要。
【参考方案1】:
add esp
不会这样做,ret 12
会这样做。
——小丑
【讨论】:
以上是关于通过中间函数调用 WriteConsole 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章
C++中用writeconsole函数往控制台写字符串出现乱码,求救!
如何使用 WinApi 的 WriteConsole 打印 LOCAL 字节