gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 06:40:30 25 4
gpt4 key购买 nike

抱歉我的英语不好

我正在努力提高我的 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
};

 int ( *asmRoutine)(int, int, int) = ( int (*)(int, int, int)) asmRoutine_body;
int ret = asmRoutine(77,66,55);

据我所知应该有效,但它没有

我查了一下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 指令上

为什么?以及我应该怎么做才能让它为我工作(我喜欢写汇编例程这样)

冷杉

//编辑

这是应该得到 float4* vector a 和 b 的 sse 例程制作点积并将结果放入 float4* c(float4 是 4 个 float 的结构或表)

(奇怪,因为它应该只获取两个 vector 并返回一个 float 通过 eax 但我得到了 if 可能来自互联网并且没有时间测试并重写它)

    /*
enter 0, 0 ; 0034 _ C8, 0000, 00
mov eax, dword [ebp+8H] ; 0038 _ 8B. 45, 08
mov ebx, dword [ebp+0CH] ; 003B _ 8B. 5D, 0C
mov ecx, dword [ebp+10H] ; 003E _ 8B. 4D, 10
movups xmm0, oword [eax] ; 0041 _ 0F 10. 00
movups xmm1, oword [ebx] ; 0044 _ 0F 10. 0B
mulps xmm0, xmm1 ; 0047 _ 0F 59. C1
movhlps xmm1, xmm0 ; 004A _ 0F 12. C8
addps xmm1, xmm0 ; 004D _ 0F 58. C8
movaps xmm0, xmm1 ; 0050 _ 0F 28. C1
shufps xmm1, xmm1, 1 ; 0053 _ 0F C6. C9, 01
addss xmm0, xmm1 ; 0057 _ F3: 0F 58. C1
movss dword [ecx], xmm0 ; 005B _ F3: 0F 11. 01
leave ; 005F _ C9
ret ; 0060 _ C3
*/

char asmDot_body[] =
{
0xC8, 0x00, 0x00, 0x00,

0x8B, 0x45, 0x08,
0x8B, 0x5D, 0x0C,
0x8B, 0x4D, 0x10,

0x0F, 0x10, 0x00,
0x0F, 0x10, 0x0B,

0x0F, 0x59, 0xC1,
0x0F, 0x12, 0xC8,
0x0F, 0x58, 0xC8,
0x0F, 0x28, 0xC1,
0x0F, 0xC6, 0xC9, 0x01,
0xF3, 0x0F, 0x58, 0xC1,
0xF3, 0x0F, 0x11, 0x01,
0xC9,
0xC3
};


void (*asmAddSSE)(float4*, float4*, float4*) = (void (*)(float4*, float4*, float4*)) asmDot_body;

float4 a = {1,2,1,0};
float4 b = {1,2,3,0};
float4 c = {0,0,0,0};

asmAddSSE(&a,&b,&c);

//编辑L8R

找到了!它非常酷而且很棒 (传递参数以及 fpu 甚至 sse) 我很高兴

tnx necrolis 表示它在你的系统上工作,

我开始尝试使用编译器开关设置对齐和还禁用了一些,它是 -pr (使用 fastcall )已启用,我应该将其关闭

(有两个 compile.bat - 一个用于正常编译和第二个用于 olso 生成程序集,并且没有 -pr 开关其次,我写的 abowe asm 代码没问题 - 但我的正常compile.bat 生成的 fastcall 调用 ant 它会失败!)

最佳答案

您的第一个问题是您假设代码是可执行的,如果幸运的话,DEP 关闭并且您可以从您的堆栈执行代码,但通常(99.99% 的时间)您需要 分配可执行内存来执行此操作。其次,像你这样写出纯机器代码是可怕的,而且容易出现错误,如果你觉得你不能使用编译器提供的内联汇编程序,请使用类似 AsmJIT 的代码。相反(或任何其他内存中的汇编程序)。

然而,您的代码工作正常(当使用 __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

关于fpu 指令崩溃,asm 代码不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9052946/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com