سؤال

أدرك أن هذا الأمر خاص بالمترجم، لكن توقعاتي هي أن موضع المحدد البعيد يجب أن يكون منطقيًا لأولئك الذين يفهمون المؤشرات حقًا.

لذا، لدي تطبيقان يتشاركان في مساحة ذاكرة المعالج بالكامل.

يحتاج التطبيق "أ" إلى استدعاء الدالة foo الموجودة في التطبيق "ب".

أعرف موقع الذاكرة للوظيفة foo.

لذلك يجب أن يعمل هذا، في التطبيق أ:

typedef int (* __far MYFP)(int input);

void somefunc(void)
{
   int returnvalue;
   MYFP foo;

   foo = (MYFP) 0xFFFFFA;

   returnvalue = foo(39);
}
  • هل __far في المكان الصحيح في typedef؟
  • هل أحتاج إلى إضافة __far إلى طاقم الممثلين (MYFP)؟
  • تشير بعض المعلومات إلى أن استدعاء foo لا يحتاج إلى إلغاء الإشارة إليه، ما هي تجربتك؟
  • ما الذي يبدو غير صحيح في هذا الأمر، أو ربما أحاول تحقيق ذلك؟

  • هل هناك طريقة أفضل للقيام بذلك؟

يحرر:

هذا موجود على جهاز مضمن (جهاز Freescale S12XEQ) باستخدام Code Warrior.إنه جهاز 16 بت مع مساحة ذاكرة 24 بت، لذا نعم، فهو مجزأ/مخزن.

-آدم

هل كانت مفيدة؟

المحلول

هل __far في المكان الصحيح في typedef؟

[تحرير، ردًا على تعليق ChrisN -- شكرًا]

هذه ميزة تعتمد على المترجم، لأنها ليست جزءًا من ANSI C.وفقًا لدليل المترجم <http://www.freescale.com/files/soft_dev_tools/doc/ref_manual/CW_Compiler_HC12_RM.pdf>، الفصل 8، لقد قمت بوضعه بشكل صحيح.في المترجمين الآخرين، قد تحتاج إلى عكس الترتيب.يجب أن يكون من السهل جدًا معرفة ذلك، نظرًا لأن أحد الخيارين بالضبط سيتم تجميعه مع أي مترجم معين.

هل أحتاج إلى إضافة __far إلى طاقم الممثلين (MYFP)؟

لا، إنه جزء من النوع.

تشير بعض المعلومات إلى أن استدعاء foo لا يحتاج إلى إلغاء الإشارة إليه، ما هي تجربتك؟

يمكن إلغاء الإشارة إلى مؤشرات الوظائف بشكل اختياري في لغة C.السطران التاليان صالحان للقيام بنفس الشيء تمامًا:

foo = (MYFP)0xFFFFFA;
returnvalue = foo(39);  // 1
returnvalue = (*foo)(39);  // 2

ما الذي يبدو غير صحيح في هذا الأمر، أو ربما أحاول تحقيق ذلك؟

لقد فعلت ذلك بشكل صحيح تماما.

نصائح أخرى

ال __far تم استخدام الكلمة الأساسية، على الأقل في عالم MS، عند إنشاء ثنائيات تستخدم الذاكرة المجزأة.أنت بحاجة إلى فهم نظام الذاكرة 8086 لفهم هذا.قام 8086 بتقسيم الذاكرة إلى أجزاء، وكان طول كل مقطع 64 كيلو بايت، لذلك يحتاج كل عنوان في المقطع إلى 16 بت.وجاءت العناوين على شكلين:القريب والبعيد.كان العنوان القريب 16 بت وكان عبارة عن إزاحة في المقطع الحالي، وهو عنوان CS وDS وES وSS اعتمادًا على التعليمات، وكان العنوان البعيد 32 بت ويتكون من مقطع وإزاحة.في 8086، كان العنوان المطلق هو 16 * مقطع + إزاحة، مما يوفر نطاقًا قابلاً للعنونة يبلغ 1 ميجابايت.

إذا كنت لا تستخدم نظام ذاكرة مجزأة، ويبدو أنك لا تستخدمه، فإن جميع العناوين لها نفس عدد البتات، لذا فإن التمييز القريب/البعيد ليس ضروريًا مما يعني أنه من المحتمل أن يتجاهل المترجم الكلمة الأساسية.

هذا مقتطف من التعليمات البرمجية يعمل من مشروع أعمل عليه.إنه Paradigm C++، لذا فهو يستخدم بعض إصدارات Borland.وحدة المعالجة المركزية التي تستخدمها هي نسخة 8086، لذا فهي ذاكرة مجزأة بحجم 20 بت.

void softSerial0SR(unsigned16);
void (__far *softHandler)(unsigned16);

أقوم بتهيئة softHandler إلى 0 دون شكوى.

ثم،

softHandler = softSerial0SR;

في رمز الإعداد.

لاستدعائها، ما عليك سوى استدعاء softHandler كدالة عادية.

لاحظ أن هذا الرمز تم تعديله قليلاً من أجلك من الكود الفعلي الذي أملكه.

تم إنشاء كلا البرنامجين بواسطة نفس المترجم/الخيارات، لذا فهما يستخدمان نفس OBI؟

أوافق على أن الكود يبدو جيدًا - في هذه الحالة، سأقوم بتفكيك الكود الذي تم إنشاؤه ومعرفة ما إذا كان يعمل بشكل صحيح.يجب أن يكون هناك 10 تعليمات فقط على الأكثر - وبعد ذلك ستعرف على وجه اليقين ما إذا كانت ناجحة أم لا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top