2012-01-29 1 views
0

жаль моего слабого английскогоаварии на инструкции FPU и ассемблерный код не работает

им пытаются улучшить свои 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); 

должен работать как далеко как я знаю, но это не

Я посмотрел в asm gener ованные от kompiler и кажутся правильными

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 (или 66 или 55 для EBP + 12 EBP + 16)

2) второй беда в том, что этот способ вызова машинный код работы для арифметических команд формируют меня, но он выходит из строя ( -анкету какой-то способ исключения системы) на FPU или SSE инструкции

почему? и то, что я должен сделать, чтобы заставить его работать на меня (я хотел бы написать сборку процедуры такого способа)

ель

// EDIT

это сс процедура, которая должна получить float4 * вектор а и б сделать скалярное произведение и положить результат в float4 * с (float4 это структура или таблица 4 поплавками)

(странно Couse он должен anly получить два вектора и возвращает поплавок на EAX, но я получил, если форма Интернет, возможно, не получил ни минуты дотест и переписать его)

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

// EDIT l8r

нашел!и это работает экстремально круто & большие (проходящие аргументы, а также FPU и даже сс) Im счастливых

TNX necrolis для заявив, что она работает на системе Yr,

Я начал пробовать с компилятором переключатели tử набора до выравнивания и также отключить некоторые, и это было -pr (использование азЬсаЙ), который был enebled и я должен отключить его

(получил два compile.bat-х - один для нормальной компиляции и вторых для Olso порождающего узла и нет -pr в секунд, так что код asm, который я написал abowe, в порядке - но у меня нормальный compile.bat сгенерированный fastcall вызывает ant it go bum!)

+2

Вы не используете ассемблер. Вы пишете машинный код. Получите сборщик. –

+0

Это может привести к запуску: http://unixwiz.net/techtips/win32-callconv-asm.html –

+0

Как насчет того, чтобы пошаговую инструкцию по команде в отладчике? Это скажет вам, что не так с вашим кодом. –

ответ

4

Ваша первая проблема заключается в том, что вы предполагаете, что код является исполняемым, если вам повезет, DEP выключен, и вы можете выполнить код из своего стека, но в целом (99,99% времени) вы должны нуждаться в, чтобы выделить исполняемую память для этого. Во-вторых, выписывание чистого машинного кода, как вы делаете, является ужасным и подверженным ошибкам, если вы считаете, что не можете использовать встроенный ассемблер, предоставленный вашим компилятором, вместо этого используйте вместо него (например, AsmJIT) (или любой другой ассемблер в памяти).

Ваш код, однако, работает нормально однако (при вызове с использованием __cdecl), когда после устранения этих проблем его все еще небезопасно. (Я запустил его и получил ожидаемый результат от 77, после, поместив его в исполняемую память). Вы, вероятно, столкнетесь с проблемами в будущем с фиксацией виртуальных и абсолютных вызовов/длинных переходов, что сделает этот еще сложным.

Ваши сбои в инструкциях FPU и SSE в основном связаны с проблемами выравнивания, но невозможно сказать без системного кода, вашей сборки или того, какой процессор вы используете, и в таких случаях лучше всего использовать отладчик, такой как 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

+0

не могли бы вы объяснить: «Ваш код, однако, отлично работает, но (...) я запустил его и получил ожидаемый результат» - означает ли это, что пример с asmRoutine (77,66,55) работает для вас ? MUCH TNX для предложения выравнивания - я использую старый pentium 4/Win XP здесь (и старый borland 55 - работает нормально для моих чистых игр winapi) –

+0

@ user982377: да, он отлично работает (я получаю 77), я действительно добавлю используемый код. вы должны серьезно рассмотреть возможность использования более нового компилятора .... – Necrolis

+0

может быть, но я использую только c и pure winapi, и он не устарел в такой области i notiice (быстро компиляция, и мне нравится, получился хороший редактор и т. д.) - как в asm, tnx для информации, я также попробую отредактировать мой пост и включить в него какую-то процедуру sse, которая может быть повреждена для меня, вы также можете проверить, будет ли она работать в вашей системе? –

 Смежные вопросы

  • Нет связанных вопросов^_^