Skip to content

لهجةُ التجميعِ العربيّة

حين لا تكفيك مدمَجةٌ، تنزلُ إلى التجميع. وفي ص طريقانِ لا واحد، وفرقُهما جوهريٌّ لا ذوقيّ:

تجميع … نهاية@تجميع("...")
القاعدةgr.adv.asm_dialectgr.adv.inline_asm
النصّمنمنماتٌ عربيّةٌ مفحوصةسلسلةُ مُجمِّعٍ خام
الفحصمعجمُ معماريّةِ الهدفلا فحص
المراسي٢٩ بذرةً٢
bash
$ find tests/behavior/rules_matrix/60_advanced/gr.adv.asm_dialect -name '*.ص' | wc -l
29
$ find tests/behavior/rules_matrix/60_advanced/gr.adv.inline_asm -name '*.ص' | wc -l
2

@تجميع الخامُّ حدٌّ مُعلَن

مرساتانِ اثنتانِ لا غير، وهو مُعلَنٌ حدًّا في حدودِ المسار. فإن كان لِما تريدُه منمنمةٌ في المعجم، فالكتلةُ المفحوصةُ أوثقُ بمرتبة.

١ · الكتلةُ المفحوصة

sad
دالة أوقف_المعالج() لا_ترجع
    تجميع
        عطّل_المقاطعات
        حلقة: أوقف
        اقفز حلقة
    نهاية
نهاية
llvm
call void asm sideeffect alignstack "cli\0A\09hlt", ""()

عناصرُ الكتلة، كما يُعلِنُها language-truth/dialects/assembly.yaml:

العنصرالصيغة
الفاتحةُ والخاتمةتجميعنهاية (وبينهما متطاير اختياريّة)
فاصلُ المعاملاتالفاصلةُ العربيّةُ ،
التعليق#
اللصيقةاسم:
السجلّاسمٌ عربيٌّ من جدولِ سجلّاتِ المعماريّة
الثابتعددٌ (بأرقامٍ عربيّةٍ أو هنديّة)
العنونة[القاعدة + العدّاد × ٤ + ٨]
متغيّرُ ص{اسم} ⇒ ربطٌ تلقائيٌّ بقيدِ InlineAsm
التلويثيلوّث(الذاكرة، الأعلام)~{memory} · ~{cc}

٢ · متغيّرُ ص داخلَ الكتلة

sad
متغير أ = 5
متغير ب = 3
متغير ناتج = 0
تجميع
    انقل {ناتج}، {أ}
    اجمع {ناتج}، {ب}
نهاية
اطبع_سطر(ناتج)

يُترجَمُ على x86_64 برمزِ خروجٍ صفر. الترتيبُ الوجهةُ أوّلًا ثمّ المصدر على المعماريّاتِ الأربعِ جميعًا — والفرقُ في النكهةِ المُصدَرةِ وحدَها.

لكنّ الرتبةَ ليست محمولة

اضرب معاملانِ على aarch64 وriscv64 (الوجهةُ تُكرَّرُ مصدرًا أوّل في العتاد)، ومعاملٌ واحد على x86_64 وi686 (mul بكتاباتٍ ضمنيّةٍ في المركم والبيانات). فالمرسى basic/005_aarch64_three_operand.ص يحملُ @arch: aarch64 riscv64 صراحةً، والصيغةُ ذاتُها على x86 تُرفَض — مقيسًا:

⛔ [SEM026] المنمنمة «اضرب» تتطلّب 1 معاملًا، ووُجد 2.

فراجِعْ حقلَ operands في معجمِ هدفِك قبلَ أن تفترضَ الحمل.

٣ · أربعُ معماريّاتٍ بأربعةِ معاجم

قِيسَت من language-truth/dialects/assembly_mnemonics/:

المعجممنمنمةسجلًّابادئةُ السجلّبادئةُ الثابتالترتيبالعنونة
x86_64٦٨٣٤%$المصدرُ أوّلًاإزاحة(قاعدة)
i686٧٠٢٢%$المصدرُ أوّلًاإزاحة(قاعدة)
aarch64٧٦٦٦#الوجهةُ أوّلًا[قاعدة، إزاحة]
riscv64٤٢٤٦الوجهةُ أوّلًاإزاحة(قاعدة)
المجموع٢٥٦
لماذا riscv64 هي البرهان

نكهتُها تركيبةٌ لم تظهر في الثلاثةِ السابقة: الوجهةُ أوّلًا وصريحةٌ كـAArch64، والعنونةُ 8(x1) كـAT&T، ولا بادئةَ لسجلٍّ ولا لثابتٍ أصلًا. فلو كان المحورانِ مقترنَينِ في الخافض (وجهةٌ-أوّلًا ⇒ أقواسٌ مربّعة) لظهرَ العطبُ هنا حتمًا. والاختبارُ الحاسم: المصدرُ نفسُه لهدفَين ⇒ نصّانِ مختلفان (test_asm_riscv64.py).

خمسُ فئاتٍ في كلِّ معجم: نقل_وبيانات · حساب · منطق_وبتّات · قفز_وتحكّم · مقاطعات_ونظام (وسادسةٌ سلاسل_وذاكرة في عائلةِ x86). وأمثلة: انقل · اجمع · وافق · ضمّ · خالف · اقفز_إذا_ساوى · عطّل_المقاطعات · أوقف · حمّل_عنوان.

الاسمُ يُحمَل، والتعليمةُ لا تُحمَل

أوقف تُخفَضُ hlt على x86 وwfi على RISC-V؛ وعطّل_المقاطعات هناك ليست cli بل csri mstatus, 8. فالاسمُ العربيُّ مشتركٌ حيث الدلالةُ مشتركة، لا حيث الترميزُ مشترك.

⚠️ وتشخيصُ SEM025 أعلاه يعدُّ ستًّا «محمولةً على المعماريّاتِ كلّها» ومنها قارن — ومعجمُ riscv64 نفسُه يقول: «لا «قارن» في RISC-V: المقارنةُ تُنتِجُ قيمةً أو تُدمَجُ في القفز» (المُعلَنُ هناك قارن_أصغر). فاعتمِدْ على المعجمِ لا على نصِّ الاقتراح.

٤ · التشخيصاتُ الخمسة

كلُّ ما يلي مخرَجٌ حقيقيّ.

SEM025 — منمنمةٌ خارجَ المعجم

⛔ [SEM025] المنمنمة «اجمع_رباعي» غير موجودة في معجم لهجة التجميع.
   هل تقصد: اجمع_بالحمل، اعكس_البتات، خزن_مربعا؟
   💡 استعمل منمنمة من معجم معماريّة الهدف (انقل/اجمع/قارن/اقفز/
      عطّل_المقاطعات/أوقف محمولة على المعماريّات كلّها)، أو أضِفها بقرار لغويّ
      في language-truth/dialects/assembly_mnemonics/<المعماريّة>.yaml
   📍 الموقع: السطر 3، العمود 9

والإضافةُ قرارُ لغةٍ في مصدرِ الحقيقة، لا رقعةٌ في C++.

SEM026 — عددُ معاملاتٍ مخالف

⛔ [SEM026] المنمنمة «اجمع» تتطلّب 2 معاملًا، ووُجد 3.
   💡 طابِق عدد المعاملات لِما يعرّفه المعجم للمنمنمة
      (مثال: «انقل وجهة، مصدر» معاملان؛ «أوقف» بلا معاملات).

SEM033 — سجلٌّ خارجَ المعجم

⛔ [SEM033] السجلّ «صفر» غير موجود في معجم سجلّات لهجة التجميع.
   هل تقصد: الصفر، سجل_٠، سجل_١؟

الاقتراحاتُ من معجمِ الهدفِ نفسِه: صفر على i686 يقترحُ سجل_٨، سجل_٩، المركم، وعلى riscv64 يقترحُ الصفر، سجل_٠، سجل_١.

والباقيان

SEM034 لمتغيّرِ ص في موضعِ مصدرٍ تكتبُه المنمنمة (بادل)، وSEM044 لهدفٍ لا معجمَ لمعماريّتِه.

٥ · حدودٌ ومزالق

  • sadc وحدَها. التوجيهانِ مُعلَنانِ compiler_optional، وحالُهما experimental.
  • رأسُ المعاملِ وذيلُه ليسا زينة. كتابةُ سجلِّ نظامٍ على AArch64 تكتبُ المُسجَّلَ أوّلًا (msr vbar_el1, x0)، فلولا operand_head ما عبّرَ المعجمُ عن جدولِ متّجهاتٍ ولا مؤقّتٍ ولا عنوانِ عودةٍ من استثناء — وهي عصبُ شفرةِ النواة.
  • مُعدِّلُ الحجمِ كذلك. حمّل_سجل_المهمة (ltr) معاملُه r/m16، فيُبَثُّ ${N:w} لا $N المجرَّد — وإلّا خرجَ ltr %eax فرفضَه المُجمِّع. وتحميلُ TR أساسُ الانتقالِ إلى الحلقة ٣.
  • الأخطاءُ تتتالى. خطأٌ واحدٌ في الكتلةِ قد يُنتِجُ ثلاثةَ تشخيصات؛ ابدأْ بالأوّلِ دائمًا.

ما يلي

مُرخَّص بموجب رخصة MIT