الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

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

مغلقمُجاب
بدأه codz في 28 مايو 2014 · 6 رد · 1,948 مشاهدة · في لغة Assembly لأنظمة 16, 32, 64 بت
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

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

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
		
         }
}
#2

حسنّا لقد حولت الكود تقريبأ  , بقي 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

}
#3

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

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

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

 

ماهي carry flag  هنا ؟

#4

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

 

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

mov eax, 0xffffffff
mov ebx, 0
add 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 في 29 مايو 2014 في 21:42

#5

شكرا اخ 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

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

#6 أفضل إجابة

أعتقد أن العملية كلها 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;
}
#7

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

 

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

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

هذا الموضوع مغلق.

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…