C fpu指令崩溃,asm代码不工作
对不起,我英语不好 我正在努力提高我的asm能力,我发现这很容易 使用机器代码例程处理它的入口点 来自c代码 我是这样使用它的C fpu指令崩溃,asm代码不工作,c,assembly,x86,calling-convention,C,Assembly,X86,Calling Convention,对不起,我英语不好 我正在努力提高我的asm能力,我发现这很容易 使用机器代码例程处理它的入口点 来自c代码 我是这样使用它的 char asmRoutineData2[] = { 0xC8, 0x00, 0x00, 0x00, // enter 0, 0 0xB8, 0xff, 0x00 ,0x00 ,0x00, // mov eax, 65538 0xC9, // leave
char asmRoutineData2[] =
{
0xC8, 0x00, 0x00, 0x00, // enter 0, 0
0xB8, 0xff, 0x00 ,0x00 ,0x00, // mov eax, 65538
0xC9, // leave
0xc3 // ret
};
int (*asmRoutine)(void) = (int (*)(void)) asmRoutineData;
int ret = asmRoutine();
它对一些例程非常有效,比如上面的
其他一些方法不起作用:
1) 我遇到了麻烦,无法获得堆栈传递的值
这样的程序
char asmRoutine_body[] =
{
0xC8, 0x00, 0x00, 0x00, //enter
0x8B, 0x45, 0x08, // mov eax, [ebp+8]
0xC9, //leave
0xC3
};
及
据我所知,它应该是有效的,但事实并非如此
我在kompiler生成的asm中查找,它似乎是正确的
mov eax,offset _asmRoutineData
push 55
push 66
push 77
call eax
add esp,12
_asmRoutineData label byte
db 200 //enter
db 0
db 0
db 0
db 139 // mov eax, dword [ebp+8H] ; 8B. 45, 08
db 69
db 8
db 201 //leave
db 195 //ret
不知道哪里出错(返回的值不是我期望的77(或ebp+12 ebp+16的66或55)
2) 第二个问题是这种调用机器代码的方式
适用于我的算术指令,但会导致应用程序崩溃
fpu或sse指令上的(某种方式的系统异常)
为什么??我应该做些什么来让它为我工作(我喜欢写汇编)
(以这种方式)
冷杉
//编辑
这是sse例程,它应该得到一个float4*向量a和b
制作点积并将结果放入float4*c
(float4是由4个float组成的结构或表)
(奇怪的是,它应该得到两个向量并返回一个浮点
是的,但我可能从互联网上得到了答案,没有时间
测试并重写它)
//编辑L8R
找到了!而且它非常酷&很棒
(传递参数以及fpu甚至sse)
我很高兴
tnx necrolis表示它正在处理yr系统
我开始尝试使用编译器开关设置对齐和
还禁用了一些,这是-pr(使用fastcall)
我要把它关掉
(有两个compile.bat,一个用于正常编译,另一个用于
第二个用于olso生成组件和中的no-pr开关
第二,我写的asm代码还行,但我的正常
compile.bat生成的fastcall调用ant它会出错!)您的第一个问题是假设代码是可执行的,如果幸运的话,DEP已关闭,您可以从堆栈中执行代码,但通常(99.99%的时间)您需要分配可执行内存来执行此操作。其次,像您这样编写纯机器代码是很可怕的,而且容易出现错误。如果您觉得无法使用编译器提供的内联汇编程序,请使用类似的程序(或任何其他内存汇编程序) 然而,您的代码运行良好(当使用
\uuu cdecl
调用时),一旦这些问题得到解决,它仍然是不安全的。(我运行了它,在将其放入可执行内存后,得到了预期的结果77)。在修复虚拟和绝对呼叫/跳远的过程中,您可能会遇到问题,这将使问题变得更加复杂
FPU和SSE指令上的崩溃很可能是对齐问题,但如果没有系统代码、程序集或正在使用的CPU,则无法判断。在这种情况下,最好使用调试器,如ollydbg(免费)并逐步执行代码
半更正代码:
static char asmRoutine_body[] =
{
0xC8, 0x00, 0x00, 0x00, //enter
0x8B, 0x45, 0x08, // mov eax, [ebp+8]
0xC9, //leave
0xC3
};
void* p = (void*)VirtualAlloc(NULL,sizeof(asmRoutine_body),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
memcpy(p,asmRoutine_body,sizeof(asmRoutine_body));
int ( *asmRoutine)(int, int, int) = ( int (*)(int, int, int))p;
int ret = asmRoutine(77,66,55);
VirtualFree(p,sizeof(asmRoutine_body),MEM_RELEASE);
printf("%d\n",ret);
输出:
77
您的第一个问题是假设代码是可执行的,如果幸运的话,DEP关闭,您可以从堆栈中执行代码,但通常(99.99%的时间)您需要分配可执行内存来执行此操作。其次,像您这样编写纯机器代码是很可怕的,而且容易出现错误。如果您觉得无法使用编译器提供的内联汇编程序,请使用类似的程序(或任何其他内存汇编程序)
然而,您的代码运行良好(当使用\uuu cdecl
调用时),一旦这些问题得到解决,它仍然是不安全的。(我运行了它,在将其放入可执行内存后,得到了预期的结果77)。在修复虚拟和绝对呼叫/跳远的过程中,您可能会遇到问题,这将使问题变得更加复杂
FPU和SSE指令上的崩溃很可能是对齐问题,但如果没有系统代码、程序集或正在使用的CPU,则无法判断。在这种情况下,最好使用调试器,如ollydbg(免费)并逐步执行代码
半更正代码:
static char asmRoutine_body[] =
{
0xC8, 0x00, 0x00, 0x00, //enter
0x8B, 0x45, 0x08, // mov eax, [ebp+8]
0xC9, //leave
0xC3
};
void* p = (void*)VirtualAlloc(NULL,sizeof(asmRoutine_body),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
memcpy(p,asmRoutine_body,sizeof(asmRoutine_body));
int ( *asmRoutine)(int, int, int) = ( int (*)(int, int, int))p;
int ret = asmRoutine(77,66,55);
VirtualFree(p,sizeof(asmRoutine_body),MEM_RELEASE);
printf("%d\n",ret);
输出:
77
您没有使用汇编程序。你在写机器代码。找一个汇编程序。这可能会让你开始:在调试器中一条一条地逐条执行你的代码指令怎么样?这会告诉你你的代码出了什么问题。没有调试器:/而且我知道我在写机器代码-没有内联程序集,不想与独立程序集对抗(它要复杂得多)。还有一些其他想法如何调试和修复它?我不知道是什么wrong@user982377你们刚才说汇编比写机器代码更复杂吗?你们并没有使用汇编程序。你在写机器代码。找一个汇编程序。这可能会让你开始:在调试器中一条一条地逐条执行你的代码指令怎么样?这会告诉你你的代码出了什么问题。没有调试器:/而且我知道我在写机器代码-没有内联程序集,不想与独立程序集对抗(它要复杂得多)。还有一些其他想法如何调试和修复它?我不知道是什么wrong@user982377你刚才是不是说汇编比编写机器代码更复杂?你能解释一下“你的代码工作得很好,但是,(..)我运行了它并得到了预期的结果”-这是否意味着asmRoutine(77,66,55)的示例对你有效?关于对齐建议的TNX很多-我在这里使用旧的pentium 4/Win XP(和旧的borland 55-适用于我的纯winapi游戏)@user982377:是的,它工作得很好(我得到77),我将实际添加使用的代码。你应该认真考虑使用一个新的编译器……也许,但我只使用C和纯WiAPI,它在这一领域没有过时。
static char asmRoutine_body[] =
{
0xC8, 0x00, 0x00, 0x00, //enter
0x8B, 0x45, 0x08, // mov eax, [ebp+8]
0xC9, //leave
0xC3
};
void* p = (void*)VirtualAlloc(NULL,sizeof(asmRoutine_body),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
memcpy(p,asmRoutine_body,sizeof(asmRoutine_body));
int ( *asmRoutine)(int, int, int) = ( int (*)(int, int, int))p;
int ret = asmRoutine(77,66,55);
VirtualFree(p,sizeof(asmRoutine_body),MEM_RELEASE);
printf("%d\n",ret);