Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C fpu指令崩溃,asm代码不工作_C_Assembly_X86_Calling Convention - Fatal编程技术网

C fpu指令崩溃,asm代码不工作

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

对不起,我英语不好

我正在努力提高我的asm能力,我发现这很容易 使用机器代码例程处理它的入口点 来自c代码

我是这样使用它的

    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);