• 0
codz

مساعدة في تحويل كود اسمبلي الى السي

سؤال

السلام عليكم

اتمنى ان يساعدني احدكم في تحويل هذه الدالة من الاسمبلى الى السي

void UpdateSampleDelta(sU32 nexttime, sU32 time, sU32 usecs, sU32 td2, sU32 *smplrem, sU32 *smpldelta){	__asm {			mov eax, [nexttime]			sub eax, [time]			mov ebx, [usecs]			mul ebx			mov ebx, [td2]			div ebx			mov ecx, [smplrem]			add [ecx], edx			adc eax, 0			mov ecx, [smpldelta]			mov [ecx], eax		         }}
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

6 إجابة على هذا السؤال .

  • 0

أعتقد أن العملية كلها 64 بت، نسخة معدلة:

typedef unsigned __int32 sU32;typedef unsigned __int64 sU64;void CUpdateSampleDelta(sU32 nexttime,                        sU32 time,                        sU32 usecs,                        sU32 td2,                        sU32 *smplrem,                        sU32 *smpldelta){  sU64 result;  result = (sU64)(nexttime - time) * usecs;  *smplrem += (sU32)(result  % td2);  *smpldelta = (sU32) (result / td2);}

يرجى الإنتباه أن الدالة المكتوبة بالأسمبلي UpdateSampleDelta تنهار عند قيم معينة، هذا اختبار (لا حاجة لإختابر القيم التي تنهار عندها):

 

#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <time.h>#include <assert.h>typedef unsigned __int32 sU32;typedef unsigned __int64 sU64;void UpdateSampleDelta(sU32 nexttime,                       sU32 time,                       sU32 usecs,                       sU32 td2,                       sU32 *smplrem,                       sU32 *smpldelta){    __asm {            mov eax, [nexttime]            sub eax, [time]            mov ebx, [usecs]            mul ebx            mov ebx, [td2]            div ebx            mov ecx, [smplrem]            add [ecx], edx            adc eax, 0            mov ecx, [smpldelta]            mov [ecx], eax                 }}void CUpdateSampleDelta(sU32 nexttime,                        sU32 time,                        sU32 usecs,                        sU32 td2,                        sU32 *smplrem,                        sU32 *smpldelta){  sU64 result;  result = (sU64)(nexttime - time) * usecs;  *smplrem += (sU32)(result  % td2);  *smpldelta = (sU32) (result / td2);}int main(int argc, char **argv){  int i;  int successes;  int exceptions;  srand((unsigned int) time(NULL));  for(i = successes = exceptions = 0 ; i < 100 ; i++)  {    sU32 nexttime = rand();    sU32 _time = rand();    sU32 usecs = rand();    sU32 td2;    sU32 smplrem1, smplrem2;    sU32 smpldelta1, smpldelta2;    smplrem1 = smplrem2 = rand();     while((td2 = rand()) == 0);    __try    {      UpdateSampleDelta(nexttime, _time, usecs, td2, &smplrem1, &smpldelta1);    }    __except(EXCEPTION_EXECUTE_HANDLER)    {      puts("Exception: UpdateSampleDelta");      exceptions++;      continue;    }    CUpdateSampleDelta(nexttime, _time, usecs, td2, &smplrem2, &smpldelta2);    assert(smplrem1 == smplrem2);    assert(smpldelta1 == smpldelta2);        successes++;  }  printf("tests %d, successes %d, exceptions %d\n", i, successes, exceptions);  return 0;}
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

حسنّا لقد حولت الكود تقريبأ  , بقي 3 اسطر الاخيرة

void  UpdateSampleDelta(sU32 nexttime, sU32 time, sU32 usecs,sU32 td2, sU32  *smplrem, sU32  *smpldelta){  *smplrem += (nexttime-time)*usecs/td2;//rest//			adc eax, 0//			mov ecx, [smpldelta]//			mov [ecx], eax}
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

المشكلة في تعليمة adc

في التوثيق تجد

ADC performs an integer addition of the two operands DEST and SRC and the carry flag

 

ماهي carry flag  هنا ؟

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

هذه التعليمة غالباً ماتشير لوجود رقم 64 بت.

 

عند جمع رقمين 32 مثل 0xffffffff + 0xffffffff، الناتج أكبر من 32 بت، لذا يتم جمع الرقم الأول مع الثاني في مسجل 32 بت، يعطي النصف الأول من النتيجة 0xfffffffe، ثم يجمع 0 + خارج الجمع 1 في مسجل آخر لينتج 0x00000001، معاً يعطيان 0x00000001:0xfffffffe = 0x1fffffffe:

mov eax, 0xffffffffmov ebx, 0add eax, 0xffffffff # eax += 0xfffffffe (carry flag = 1, في اليد واحد)adc ebx, 0          # ebx += carry flag(1) + 0# ebx:eax 0x00000001:0xfffffffe = 0x1fffffffe

لا أعرف الغرض من الدالة لكن يمكن محاكاة نتيجتها في c هكذا (تعطي نتيجة مطابقة):

typedef unsigned __int32 sU32;typedef unsigned __int64 sU64;void CUpdateSampleDelta(sU32 nexttime, sU32 time, sU32 usecs, sU32 td2,                        sU32 *smplrem, sU32 *smpldelta){  sU32 result;  result = (nexttime - time) * usecs;  *smplrem += (sU32)((sU64) result / td2 >> 32);  *smpldelta = result / td2;}
تم تعديل بواسطه Mr.B
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

شكرا اخ Mr.B و عذرا عن التأخير

 

الكود لم يشتغل او بألاحرى اشتغل و لكن لم يعطي الناتج المطلوب

هذه الدالة مأخوذة من مكتبة محرك صوتي . صاحبها كتبها فقط لتدعم visual cpp . اردت ان احولها الى mingw . 

التحويل تم بنجاح ولكن فقط بتحوييل الاسمبلي من intel syntax الى at&t .لكن اردت تحويله الى السي ليكون قابل للناقلية .

ملاحظة : الكود السابق اشتغل ايضا بحذف السطر adc eax, 0 .

في الدالة السابقة كتب الكاتب ملاحضة فوق الدالة :

// performs 64bit (nexttime-time)*usecs/td2 and a 32.32bit addition to smpldelta:smplrem

لكن لم افهم جيدا هذا التعليق

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

شكرا اخي Mr.B . الكود اشتغل بنجاح .

 

ملاحظة : visual-cpp لا يقوم بتحسين دالة ما اذا كانت تحتوي على اسمبلى . عكس gcc الذي يغير كل شىء اذا كان التحسين مفغل

لان عندما حولت الاسمبلى من intel الى at&t اشتغل الكود ولكن بدون تحسينات -o0 .  لكن مع التحسينات يحدث كراش .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .