سؤال

هل من الممكن الوصول إلى سجلات 32 بت في ج؟ إذا كان كذلك ، كيف؟ وإذا لم يكن الأمر كذلك ، فهل هناك أي طريقة لتضمين رمز التجميع في ج؟ أنا باستخدام مترجم mingw ، بالمناسبة. شكرا لك مقدما!

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

المحلول

إذا كنت تريد قراءة السجل فقط ، يمكنك ببساطة:

register int ecx asm("ecx");

من الواضح أنها مرتبطة بالمشاركة.

طريقة أخرى هي استخدام التجميع المضمّن. علي سبيل المثال:

asm("movl %%ecx, %0;" : "=r" (value) : );

هذا يخزن ecx القيمة في المتغير value. لقد نشرت بالفعل إجابة مماثلة هنا.

نصائح أخرى

ما هي السجلات التي تريد الوصول إليها؟

سجلات الغرض العام عادة لا يمكن الوصول إليها من C. يمكنك إعلان تسجيل متغيرات التسجيل في وظيفة ، ولكن هذا لا يحدد سجلات محددة تستخدم. علاوة على ذلك ، يتجاهل معظم المترجمين الكلمة الرئيسية للتسجيل وتحسين استخدام التسجيل تلقائيًا.

في الأنظمة المدمجة ، من الضروري في كثير من الأحيان الوصول السجلات المحيطية (مثل أجهزة ضبط الوقت ، وحدات تحكم DMA ، دبابيس I/O). عادة ما تكون هذه السجلات ملفوفة بالذاكرة ، بحيث يمكن الوصول إليها من ج ...

من خلال تحديد مؤشر:

volatile unsigned int *control_register_ptr = (unsigned int*) 0x00000178;

أو باستخدام المعالجة المسبقة:

#define control_register (*(unsigned int*) 0x00000178)

أو يمكنك استخدام روتين التجميع.

لاستخدام لغة التجميع, ، هناك (على الأقل) ثلاثة إمكانيات:

  1. ملف مصدر منفصل. asm مرتبط بالبرنامج. يتم استدعاء إجراءات التجميع من C مثل الوظائف العادية. ربما تكون هذه هي الطريقة الأكثر شيوعًا ولديها ميزة مفادها أن الوظائف المعتمدة على HW يتم فصلها عن رمز التطبيق.
  2. التجميع في الخط
  3. الوظائف الجوهرية التي تنفذ تعليمات لغة التجميع الفردية. هذا له ميزة أن تعليمات لغة التجميع يمكنها الوصول مباشرة إلى أي متغيرات C.

يمكنك تضمين التجميع في ج

http://en.wikipedia.org/wiki/inline_assembler

مثال من ويكيبيديا

extern int errno ؛

int funcname(int arg1, int *arg2, int arg3)
{
  int res;
  __asm__ volatile(
    "int $0x80"        /* make the request to the OS */
    : "=a" (res)       /* return result in eax ("a") */
      "+b" (arg1),     /* pass arg1 in ebx ("b") */
      "+c" (arg2),     /* pass arg2 in ecx ("c") */
      "+d" (arg3)      /* pass arg3 in edx ("d") */
    : "a"  (128)       /* pass system call number in eax ("a") */
    : "memory", "cc"); /* announce to the compiler that the memory and condition codes have been modified */

  /* The operating system will return a negative value on error;
   * wrappers return -1 on error and set the errno global variable */
  if (-125 <= res && res < 0) {
    errno = -res;
    res   = -1;
  }  
  return res;
}

لا أعتقد أنه يمكنك القيام بها مباشرة. أنت تستطيع قم بالتجميع المضمّن برمز مثل:

asm (
    "movl $0, %%ebx;"
    "movl $1, %%eax;"
); 

إذا كنت على معالج 32 بت واستخدام برنامج التحويل البرمجي المناسب ، فعندئذ نعم. تعتمد الوسائل الدقيقة على النظام والمترجم المعينين اللذين تقومون به ، وبالطبع سيجعل هذا الرمز الخاص بك غير قابل للمواصفات قدر الإمكان.

في حالتك باستخدام MINGW ، يجب أن تنظر إلى بناء جملة التجميع المضمّن لـ GCC.

يمكنك بالطبع. "Mingw" (GCC) يسمح (كمجموعات أخرى) تجميع مضمّن ، كما تظهر الإجابات الأخرى بالفعل. أي تجميع ، يعتمد على وحدة المعالجة المركزية لنظامك (Prob. 99.99 ٪ أنه x86). ومع ذلك ، فإن هذا يجعل برنامجك غير محمول على معالجات أخرى (ليس بهذا السوء إذا كنت تعرف ما تفعله ولماذا).

الصفحة ذات الصلة تتحدث عن التجميع لـ GCC هنا و هنا, ، وإذا أردت أيضًا هنا. لا تنس أنه لا يمكن أن يكون محددًا لأنه يعتمد على الهندسة المعمارية (يمكن لجامعة GCC تجميع العديد من وحدات المعالجة المركزية)

لا توجد حاجة عمومًا للوصول إلى سجلات وحدة المعالجة المركزية من برنامج مكتوب بلغة عالية المستوى: اللغات عالية المستوى ، مثل C ، Pascal ، وما إلى ذلك حيث تم اختراعه بدقة من أجل تجريد الجهاز الأساسي وجعل البرنامج أكثر آلة- لا يعتمد.

أظن أنك تحاول أداء شيء ما ولكن ليس لديك أدنى فكرة عن كيفية استخدام طريقة تقليدية للقيام بذلك.

يتم إخفاء العديد من الوصول إلى السجلات في بنيات المستوى الأعلى أو في مكالمات النظام أو المكتبة والتي تتيح لك تجنب ترميز "الجزء القذر". أخبرنا المزيد عما تريد القيام به وقد نقترح عليك بديلاً.

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