ASM呼叫中的访问冲突 [英] Access violation in ASM call
问题描述
我正在制作自己的Allegro类,因此比较容易,但是我在使用ESP时遇到了问题,我遇到了访问冲突.
I am making my own Allegro Class so is more easy but I am having problem with ESP, I am getting Access Violation.
void RBAllegro::AddText( FONT *f, int x, int y, int color, int bg, const char *format)
{
//textprintf_ex( m_Buffer, f, x, y, color, bg, format );
__asm
{
push format;
push bg;
push color;
push y;
push x;
push f;
push m_Buffer;
call textprintf_ex;
add esp, 28;
}
}
推荐答案
首先,为什么要这么做?编译器将执行吸气剂工作,并具有使其正确处理的附加优势.
您没有提供足够的信息.什么是快板班"?textprintf_ex
的调用约定是什么(例如__stdcall
,__cdecl
或什么)?由于该呼叫看起来很适合__cdecl
呼叫,因此我将其假定为__stdcall
.在这种情况下,请尝试以下代码:
Firstly, why the hell are you doing this? The compiler will do a getter job with the added advantage that it gets it right.
You haven''t provided enough information. What''s an "Allegro Class"? What''s the calling convention oftextprintf_ex
(e.g.__stdcall
,__cdecl
or what)? Since the call looks right for a__cdecl
call I''ll assume it''s__stdcall
. In that case try this code:
__asm
{
push format;
push bg;
push color;
push y;
push x;
push f;
push m_Buffer;
call textprintf_ex;
}
__stdcall
函数清理自己的堆栈.
另一方面,它可能是成员函数.在这种情况下,您将需要传递this
指针.根据调用约定,执行此操作的方式将有所不同.
总结:
__stdcall
function clean up their own stacks.
On the other hand it may be a member function. In this case you''ll need to pass the this
pointer. Depending on the calling convention how you go about doing this will vary.
In summary:
- 删除汇编代码.
- 如果您必须使用汇编代码,那么更多信息会很好.
来自文档:
From the docs:
void textprintf_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int bg, const char *fmt, ...);
你不是想念什么吗? ...提示...
为什么要使用汇编程序?那太疯狂了.您将无法优化函数调用.
...也许毕竟还不那么疯狂.
如果您在格式字符串中不使用任何格式说明符,这可能对您有用:
Aren''t you missing something? ... hint ...
Why do you use assembler? That''s just crazy. You won''t be able to optimize a function call.
...or maybe not that crazy after all.
This should probably work for you if you don''t use any format specifiers in your format string:
__asm
{
push format;
push bg;
push color;
push y;
push x;
push f;
push m_Buffer;
call dword ptr[textprintf_ex];
add esp, 28;
}
当涉及可变参数时,与尝试一次推送一个值相比,从堆栈中执行memcpy可能更好.因为在后一种情况下,您将必须解析格式字符串以了解所有参数的大小.
您可以将& f用作源开始,并使用函数中易失性变量的地址偏移量作为对存储块结尾的引用.您只需要像上面一样处理m_Buffer.
When it comes to the varadic arguments you might be better off doing a memcpy from the stack, than trying to push a value at a time. Because in the latter case you will have to parse the format string to know the size of all parameters.
You can use &f as the source start and use an offset to the address of a volatile variable located in your function as a reference to the end of the memory block. You will only have to deal with m_Buffer as you do above.
看看va_start,va_args和va_end宏.它们是专门为处理变量参数列表而设计的,包括将它们传递给带有变量参数列表的其他函数.
现在讲道...
当在流行的I/O模型中使用插入和提取运算符时,为什么在C ++中使用可变参数列表?有什么不对:
Look at the va_start, va_args and va_end macros. They''re designed explicitly for handling variable parameter lists, including passing them onto other functions taking variable parameter lists.
Now the sermon...
Why, in C++, are you using variable parameter lists when the prevailing model for I/O uses insertion and extraction operators? What''s wrong with having:
allegro_text_stream str( f, x, y, color, bg );
str << "The value of n is: " << n;
阅读Langer和Kreft撰写的"Standard C ++ IOStreams and Locales",它具有您需要的所有详细信息.
干杯,
灰
Have a read of "Standard C++ IOStreams and Locales" by Langer and Kreft, it''s got all the gory details you''ll need.
Cheers,
Ash
这篇关于ASM呼叫中的访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!