لغة التجميع

لغة التجميع أو لغة المُجمع والتي يمكن اختصارها إلى (asm)، هي أي لغة برمجة منخفضة المستوى يوجد بها تطابق قوي جدًا بين التعليمات المستخدمة في اللغة وتعليمات لغة الآلة الخاصة بمعمارية الحاسوب. نظرًا لأن التجميع يعتمد على تعليمات لغة الآلة، فقد صُمِّمَت كل لغة تجميع لمعمارية كمبيوتر محددة واحدة بالضبط. قد تسمى لغة التجميع أيضًا رمز الآلة الرمزي.
تُحَوَّل لغة التجميع إلى لغة آلة قابلة للتنفيذ بواسطة البرنامج المساعد المشار إليه باسم المُجمع، يشار إلى عملية التحويل باسم التجميع، كما هو الحال في تجميع الشيفرة المصدرية، وعادةً ما تحتوي لغة التجميع على جملة واحدة لكل تعليمه للآلة (1:1)، ولكن التعليقات والجمل هي توجيهات للمُجمِّع، ماكرو، وغالبًا ما يتم أيضًا دعم التسميات الرمزية لمواقع البرامج والذاكرة.
يُنسب مصطلح المُجمع بشكل عام إلى موريس ويلكس وديفيد ويلر وستانلي جيل في كتابهم الصادر عام 1951 بعنوان «إعداد البرامج لجهاز كمبيوتر رقمي إلكتروني» ، والذي قام باستخدام المصطلح ليعني «برنامج يجمع برنامجًا آخر يتكون من عدة أقسام في برنامج واحد».
تكون لغة التجميع خاصة بمعمارية حاسوب معينة وأحيانًا بنظام تشغيل معين. ومع ذلك، لا توفر بعض لغات التجميع نحواً محددًا لمخاطبة نظام التشغيل، ويمكن استخدام معظم لغات التجميع عالميًا مع أي نظام تشغيل، حيث توفر اللغة الوصول إلى جميع الإمكانات الحقيقية للمعالج، والتي تعتمد عليها جميع آليات طلبات النظام في النهاية، على عكس لغات التجميع، تكون معظم لغات البرمجة عالية المستوى محمولة بشكل عام عبر بنيات متعددة ولكنها تتطلب تفسير أو تحويل، وتسمى الخطوة الحسابية عندما يقوم المُجمّع بمعالجة برنامج بوقت التجميع.
تركيب لغة التجميع
تستخدم لغة التجميع أسلوب ذاكري (مُعتمد على الذاكرة بشكل كبير) لتمثيل كل من التعليمات أو كود التشغيل المنخفض المستوى للآلة، وأيضًا كل سجل معماري و وما إلى ذلك، تتطلب العديد من العمليات معاملًا واحدًا أو أكثر من أجل تكوين تعليمات كاملة، تسمح معظم المُجمعات بالثوابت والسجلات و المُسماة لمواقع البرامج والذاكرة، ويمكنها حساب للمعاملات. وبالتالي، يتم تحرير المبرمجين من الحسابات المتكررة المملة وتكون برامج المجمّع أكثر قابلية للقراءة من لغة الآلة، اعتمادًا على المعمارية، يمكن أيضًا دمج هذه العناصر للحصول على تعليمات محددة أو أوضاع التوجيه باستخدام إزاحات أو بيانات أخرى بالإضافة إلى العناوين الثابتة، تقدم العديد من المُجمعات آليات إضافية لتسهيل تطوير البرنامج، والتحكم في عملية التجميع، والمساعدة في تصحيح الأخطاء.
المصطلح
المُجمع
قارن مع: مجمع دقيق Microassembler.
عادة ما يقوم أي مُجمع حديث بتكوين كود غرضي/نهائي (Object Code) عبر ترجمة تعليمات لغة التجميع إلى شفرة تشغيل Opcode) Operation Code)، وعبر تحليل الأسماء الرمزية لمواقع تخزين البيانات بالذاكرة (Memory Locations) وغيرها من الكيانات، ويعتبر استخدام الإشارات الرمزية (Symbolic References) سمة أساسية من سمات المُجمعات، حيث يتم حفظ حسابات طويلة ومملة، وتحديث عناوين الذاكرة بعد تعديلات البرنامج. وتحتوي معظم المُجمعات على تسهيلات من نوع ماكرو تقوم بعمليات استبدال النصوص (Textual Substitution). على سبيل المثال، لتوليد متواليات قصيرة من التعليمات تعمل ضمنيا بدلا من أن تعمل في دالة.
وبصفة عامة، فإن كتابة المُجمعات -لأن المُجمع أساسا عبارة عن برنامج يتم كتابته- أسهل من كتابة مترجمات اللغات عالية المستوى، وقد ظهرت المُجمعات منذ خمسينات القرن الماضي. وتقوم المُجمعات، خصوصًا تلك المعتمدة على معمارية/هندسة حاسوبية من نوع RISC، مثل نماذج مبس (MIPS) وسبارك (SPARK) من شركة صن مايكروسيستمز وPA-RISC من شركة هيوليت باكارد ومعالجات (x86-64) بالوصول لجدولة التعليمات للدرجة المثلى، من أجل استغلال وحدة المعالجة المركزية أكفأ استغلال.
وهناك نوعين من المُجمعات، وقُسِّم النوعين على أساس عدد مرات المرور خلال الكود المطلوب لإنتاج الكود النهائي، أو البرنامج القابل للتنفيذ بمعنى آخر.
يعرف النوع الأول بالمُجمع ذو المرور الواحد، وهو المُجمع الذي يمر على الكود مرة واحدة فقط، مفترضا أن تعريف كل رموز الكود (مثل أسماء المتغيرات) سبق أي تعليمات قد تشير لهذه الرموز.
يعرف النوع الثاني بالمُجمع متعدد المرور، وهو المُجمع الذي يمر مرتين -أو أكثر من مرة- على الكود، ويقوم أثناء المرور الأول بتكوين جدول يضع فيه كل الرموز التي لم يتعرف عليها (Unresolved)، ويستخدم تلك الرموز في المرور الثاني كي يقوم بحل تلك العناوين.
أما ميزة المُجمع ذو النوع الأول «مرور واحد» فهي السرعة والتي لم تعد مهمة كما كانت يوما ما، بعد أن تطورت سرعات وإمكانيات أجهزة الكمبيوتر. أما ميزة النوع الثاني من المُجمعات التي تقوم بمرورين فيما فوق فهي أن رموز البرنامج يمكن أن تعرف في أي مكان بالشيفرة المصدرية للبرنامج. وكنتيجة لذلك، فيمكن تعريف البرنامج بطريقة أكثر منطقية وذات مغزى. على سبيل المثال، يستطيع المبرمج قراءة برامج زملاءه بسهولة أكثر. مما يجعل برامج المُجمع متعدد المرور أسهل في القراءة والصيانة -القيام بتعديلات عليها مثلا-.
أما المُجمعات عالية المستوى وذات الإمكانيات الأكثر تعقيدا، فتوفر تجريدًا أكثر للغة، يمكن توضيحه فيما يلي:
بناءات تحكم (Control Structures) أكثر تقدما.
إمكانية الإعلان عن وظائف/إجراءات عالية المستوى، واستدعائها.
أنواع بيانات مجردة (Abstract) عالية المستوى، بما في ذلك الهياكل (Structures) والسجلات (Records) والاتحادات (Unions) والأصناف (Classes) والمجموعات (Sets).
معالجة ماكرو متطورة.
مميزات البرمجة كائنية التوجه، مثل التغليف وتعدد الأشكال والوراثة والواجهات.
لتفاصيل أخرى، انظر «تصميم اللغة» أدناه.
لاحظ أنه في حالة الاستخدام المهني العادي، يتم استخدام اللفظ مُجمع بشكل غامض، فكثيرا ما يتم استخدامه للإشارة للغة التجميع نفسها، بدلا من الإشارة لـ «أداة التجميع». وبالتالي، فإن عبارة «إن نموذج CP/CMS تم كتابته بلغة التجميع Assembler ذو الاسم S/360» تختلف عن العبارة «إن نموذج ASM-H لهو مجمع تم استخدامه على نطاق واسع مع S/370».
لغة التجميع
ويتكون البرنامج المكتوب بلغة التجميع من سلسلة من التعليمات -سهلة الحفظ (Mnemonics) والتي تماثل دفعة من التعليمات التنفيذية (Executable)، وعندما يتم ترجمة هذا الكود عبر المُجمع، يمكن تحميل هذا الكود إلى الذاكرة وتنفيذه.
على سبيل المثال، فإن التعليمة التالية الخاصة بمعالج من نوع x86/IA-32 تخبره بنقل قيمة مكونة من ثمانية بايت إلى المسجل. هذه التعليمة مكتوبة بكود ثنائي يمثل لغة الآلة. الكود الثنائي لهذه التعلية هو 10110 متبوعًا بمعرّف 3 بت للمسجل المراد إستخدامه. المعرف الخاص بالمسجل AL هو 000، لذلك يقوم الكود التالي بتحميل سجل AL بالبيانات 01100001.10110000 01100001يمكن جعل كود الكمبيوتر الثنائي السابق أكثر قابلية للقراءة من خلال التعبير عنه بالنظام الست عشري على النحو التالي.B0 61
ومع قرائتك للسطر التالي تشعر بأن تمثيل الكود عبر لغة التجميع أسهل للقراءة وللتذكر (مثال باستخدام تراكيب شركة إنتل)، انظر استذكارMOV AL, #61h
وتعني هذه التعليمات ما يلي:
انقل القيمة 61h (والتي تعني بالنظام العشري القيمة "97"؛ حيث تعني اللاحقة "h" النظام الست-عشري؛ وتعني علامة الهاش "#" أن يتم نقل القيمة 97 ولا تعني أن يتم نقل القيمة المخزنة في عنوان الذاكرة رقم 97) إلى سجل المعالج ذو الاسم "AL".
الأمر "mov" يكتب بكود التشغيل بالشكل 1011، ويقوم بنقل القيمة المذكورة بمعامل Operand الأمر الثاني، إلى السجل المذكور عبر المعامل الأول. وقد اختار «مصمم مجموعة التعليمات» تلك الحروف الثلاثة mov لتمثيل الأمر، مما يجعل الأمر سهلا على المبرمج لتذكر واستخدام الأمر. ويتم الفصل بين مجموعة والمعطيات التي تتبع شفرة التشغيل عبر فاصلة "،"؛ إن ما سبق هو نموذج جيد لجملة من جمل لغة التجميع.
وأثناء الممارسة يقوم العديد من المبرمجين بإسقاط الكلمة Mnemonic (أمر سهل التذكر) وإطلاق وصف «كود تشغيلي» Opcode على اللفظة "mov"، وذلك خطأ تقني بكل تأكيد. فعندما يفعلون ذلك، فهم يشيرون إلى الكود الثنائي والذي تمثله لغة التجميع. ولتوضيح الأمر بشكل آخر، إن الأمر سهل التذكر مثل الأمر mov ليس كودا تشغيليا Opcode، لكنه يمثل أو يرمز إلى الكود التشغيلي، لذلك فعندما يشير أحدهم إلى «الكود التشغيلي للأمر mov» فهو يقصد إلى الإشارة للكود التشغيلي الثنائي ولا يشير إلى الأمر المكتوب بلغة التجميع. وحاليا، يوجد عدد محدود من المبرمجين الذين يحتاجون للتعامل مع النماذج الثنائية التي تمثل كود التشغيل الخاص بتعليمات معينة، فهذا التمييز لم يعد يحتاجه أحد بين المبرمجين -لم تعد عملية البرمجة التي تطورت إمكانياتها تحتاجه-، لكنه مطلوبا جدا في أوساط مصممي المعالجات Processor Designers.
يمكن أن يكون بناء جملة MOV أكثر تعقيدًا كما تظهر الأمثلة التاليةMOV EAX, [EBX] ; Move the 4 bytes in memory at the address contained in EBX into EAX
MOV [ESI+EAX], CL ; Move the contents of CL into the byte at address ESI+EAX
MOV DS, DX ; Move the contents of DX into segment register DS
وتُحَوَّل لغة التجميع إلى لغة الآلة عبر المُجمع، وتتم العملية العكسية عبر برنامج يدعى المفكك. وبخلاف اللغات عالية المستوى، فدائما ما يكون هناك توافق أو تناظر بين التعليمات البسيطة المكتوبة بلغة التجميع وبين التعليمات المكتوبة بلغة الآلة. إلا أنه، وفي بعض الحالات، يمكن للمجمع أن يخرج تعلميات من نوع Pseudoinstructions، والتي يتم تمثيلها عبر عدة تعليمات بلغة الآلة، من أجل القيام بوظائف يشيع الاحتياج لها. على سبيل المثال، بفرض أن هناك آلة ينقصها الأمر Branch-if-greater-or-equal «انتقل لمكان آخر إذا ساوت القيمة x أو زادت عن x» في مجموعة أوامر المُجمع الخاص بها، يمكن لحل هذه المشكلة، أن يقوم المُجمع بتوفير تعليمات Pseudoinstructions تجمع بين الأمرين "Set if less than" و"branch if zero" -الأمر الأخير يعمل مع ناتج الأوامر التي تسبقه-. وتوفر معظم المُجمعات ذات «المميزات الكاملة» Full-Featured، لغة ماكرو ثرية (والتي يتم مناقشتها أدناه) يتم استخدامها من قبل الشركات Vendors والمبرمجين لإنتاج كود وتسلسل بيانات أكثر تعقيدا.
غني عن الذكر، أن كل بناء حاسوبي وكل معالج له لغة الآلة الخاصة به. وعلى هذا المستوى، تكون كل تعليمة ممثلة بشكل بسيط بحيث يتم تنفيذها من خلال عدد صغير نسبيا من الدوائر الإلكترونية Electronic Circuits. وتختلف أجهزة الكمبيوتر باختلاف نوع وعدد العمليات التي تدعمها. على سبيل المثال، فإن آلة جديده من نوع 64 بت تتكون من نوع مختلف من الدوائر التي تمتلكها آلة من نوع 32 بت. وقد يختلفان أيضا في أحجام وأعداد المسجلات في كل منهما، وقد يختلفان أيضا في تمثيل البيانات داخل مخازن البيانات -المخازن مثل: الذاكرة والمسجلات-. وفي حين أن معظم أجهزة الكمبيوتر التي تستخدم في الأغراض العامة قادرة على تنفيذ نفس الوظائف، فإن طريقة أداء كل جهاز تختلف عن بقية الأجهزة؛ وتعكس لغات التجميع الخاصة بكل منهم هذا الاختلاف.
وقد تحتوي مجموعة واحدة من أوامر لغة التجميع "Instruction Set" مجموعات متعددة من التراكيب اللغوية التي تستخدم في كتابة الأوامر Mnemonics. وفي مثل هذه الحالات، فإن المجموعة الأكثر استخداما هي تلك التي توفرها الشركة المصنعة -للنظام الحاسوبي- وتستخدمها في وثائق منتجها Documentation.
تصميم اللغة
العناصر الأساسية
تتكون أي لغة تجميع من 3 أنواع من جمل التعليمات والتي تستخدم في تعريف عمليات البرنامج:
أوامر كود التشغيل Opcode
مقاطع البيانات
توجيهات لغة التجميع Directives
أوامر كود التشغيل
عادة ما تكون التعليمات (الجمل) في لغة التجميع بسيطة للغاية، بعكس تلك الموجودة في لغات البرمجة عالية المستوى. بصفة عامة، فإن "كود التشغيل" هو اسم رمزي لتعليمة تنفيذية واحدة مكتوبة بلغة الآلة، ويوجد على الأقل أمر واحد من الكود التنفيذي محدد لكل تعليمة مكتوبة بلغة الآلة. وكل تعليمة تتكون عادة من "عملي أحد Byte، مكودة داخل التعليمة نفسها)، ويمكن أن تكون "غير مباشرة" وتشير إلى عنوان الذاكرة الذي يتم تخزين البيانات فيه. ويتحدد ذلك عبر البنية الأساسية للمعالج Architecture: فالمُجمع يعبر عن كيفية عمل هذه البنية فحسب.
مقاطع البيانات
هناك تعليمات تستخدم في تحديد عناصر البيانات Data Elements التي تحمل البيانات وتحمل المتغيرات. وتحدد تلك العناصر: نوعية البيانات، طول البيانات، وموائمة البيانات Alignment.ويمكن لتلك التعليمات أيضا أن تحدد إذا ما كانت تلك البيانات متاحة لبرامج خارجية Outside Programs (برامج يتم تجميعها بشكل منفصل عن البرنامج الذي يحتوي البيانات)، أو أنها متاحة فقط للبرنامج الذي يحمل قسما يحتوي تعريف تلك البيانات.
توجيهات لغة التجميع Assembly Directives/ Pseudo-Ops
«توجيهات لغة التجميع» Assembly Directives هي تعليمات يتم تنفيذها عن طريق المُجمع أثناء وقت التجميع Assembly Time، ولا يتم تنفيذها عبر وحدة المعالجة المركزية في وقت تنفيذ البرنامج.ويمكن لتلك التوجيهات أن تجعل لغة التجميع الخاصة بالبرنامج تعتمد على «معامل» يتم إدخاله عبر المبرمج، بحيث يمكن تجميع البرنامج الواحد بأكثر من طريقة، وربما من أجل تطبيقات مختلفة -لكل نسخة مجمعة مختلفة-.ويمكن أن تستخدم «التوجيهات» Directives أيضا للتلاعب Manipulate بطريقة عرض البرنامج Presentation، مما يجعل البرنامج أسهل في القراءة والصيانة من ناحية المبرمج.
(على سبيل المثال، يمكن استخدام الـ Pseudo-Ops في حجز مساحات تخزين وملأها بقيمها المبدأية بشكل اختياري.)وغالبا ما تبدأ أسماء العمليات من نوع Pseudo-Ops بنقطة Dot لتمييزها عن باقي تعليمات الجهاز.
وتدعم بعض المُجمعات أيضا تعليمات من نوع Pseudo-Instructions، والتي تقوم بتوليد تعليمتين أو أكثر من تعليمات الجهاز Machine Instructions.
وتسمح المُجمعات الرمزية Symbolic للمبرمجين بتحديد أسماء من اختيارهم (علامات أو رموز) لمواقع الذاكرة Memory Locations. وعادة ما يتم إعطاء كل متغير وكل ثابت Constant أسماء، بحيث يمكن الإشارة لتلك العناصر داخل التعليمات بأسمائها، وبالتالي يساعد المبرمج نفسه في توثيق الكود الذي يكتبه Self-Documenting.وفي الكود القابل للتنفيذ، يتم ربط اسم كل «روتين فرعي» Subroutine بـ نقطة دخوله Entry Point، بحيث يتم استدعاء الروتين الفرعي عبر استخدام اسمه. وداخل الروتينات الفرعية، يتم إعطاء علامات Labels لوجهات الأمر GOTO. وتدعم بعض المُجمعات «رموزا محلية» Local Symbols والتي تختلف مفرداتها عن الرموز العادية (مثال: استخدام التركيب "10$" كوجهة للأمر GOTO).
وتوفر معظم المُجمعات إدارة مرنة للرموز، بحيث تتيح للمبرمجين: إدارة مساحات إسمية مختلفة Namespaces، حساب الإزاحات بشكل آلي داخل هياكل البيانات Data Structures، وتحديد تسميات/علامات Labels تشير إلى قيم حرفية أو إلى ناتج حسابات بسيطة تؤدى عبر المُجمع. وتستخدم التسميات/العلامات Labels أيضا لتهيئة الثوابت Constants والمتغيرات مع عناوين قابلة للإعادة التعيين Relocatable Addresses.
وحدات الماكرو
تدعم العديد من المُجمعات وحدات الماكرو ، وهي عبارة عن رموز مُعرفة عن طريق المبرمج وتحوي مجموعة من سطور النص المتسلسلة. هذا التسلسل للسطور النصية، قد يحوي سلسلة من التعليمات، أو سلسلة من تعليمات Pseudo-Ops خاصة بالبيانات. وطالما تم تعريف الماكرو عبر استخدام الـ Pseudo-Op المناسب، فإنه من الممكن استخدام اسمه، مثلما يتم استخدام أسماء الأوامر Mnemonic تماما. وعندما يقوم المُجمع بمعالجة جملة من تلك النوعية، فإنه يقوم باستبدال الجملة التي تحوي اسم الماكرو بالسطور النصية المرتبطة بذلك الماكرو. بعد ذلك، يقوم بمعالجة تلك السطور كما لو أنها قد ظهرت في ملف الشيفرة المصدرية (متضمنا، كما يحدث في بعض المُجمعات، محتويات أي ماكرو قد يظهر في السطور المُستبدلة -ماكرو داخل ماكرو-).
وبما أن وحدات الماكرو يمكن أن تحمل أسماء قصيرة يتم توسعتها إلى سطور طويلة من الكود، فإن وحدات الماكرو يمكن أن تستخدم لتجعل البرامج المكتوبة بلغة التجميع تبدو وكأنها أقصر (بمعنى أن يتطلب بناء التطبيق عددا أقل من سطور الكود، كما هو الحال مع لغات البرمجة عالية المستوى). ويمكن أيضا أن يتم استخدامها لإضافة هياكل Structures عالية المستوى إلى البرامج المكتوبة بلغة التجميع، ويمكن أن تقدم -بشكل اختياري- كود يستخدم لإدارة وإصلاح الأخطاء البرمجية بشكل ضمني، عبر المعاملات وعبر خصائص أخرى.
معظم المُجمعات تمتلك وحدات ماكرو مدمجة Built-in من أجل الاستدعائات عبر النظام System Calls ومن أجل بعض تسلسلات الكود الخاصة.
وغالبا ما تسمح المُجمعات لوحدات ماكرو بأن تمتلك معاملات. وبعض المُجمعات تمتلك لغة ماكرو معقدة جدا، وتقوم بدمج عناصر هذه اللغة عالية المستوى للقيام بوظائف متعددة: معاملات اختيارية Optional Parameters، متغيرات رمزية، جمل شرطية، معالجة لسلاسل الحرفية Strings، عمل عمليات حسابية، وجميع تلك الأشياء يمكن إعادة استخدامها أثناء تنفيذ وحدات ماكرو بعينها، وتسمح -تلك المُجمعات- لوحدات الماكرو بحفظ السياق Context أو تبادل المعلومات بين بعضها البعض. ولذلك، فإن الماكرو يمكنه توليد عدد ضخم من تعليمات لغة التجميع أو من تعريفات البيانات، استنادا إلى معاملات الماكرو Arguments. ويمكن استخدام ذلك لتوليد هياكل بيانات ذات شكل «سجلي» Record-Style، ويمكن استخدام ذلك أيضا لتولييد دوارات مبسوطة Unrolled Loops، على سبيل المثال، ويمكن أيضا استخدام نفس التقنية في توليد خوارزميات كاملة تستند على معاملات معقدة. ويمكن اعتبار مؤسسة تستخدم هذه النوعية من لغات التجميع والتي تم تمديد قدراتها بشكل مكثف عبر استخدام مجموعة وحدات الماكرو، يمكن اعتبارها وكأنها تستخدم لغة برمجة عالية المستوى، حيث أن مبرمجي الشركة لا يعملون مع عناصر الكمبيوتر المفاهيمية ذات المستوى المنخفض (مثال: لا يعملون مع المسجلات).
وقد تم استخدام وحدات الماكرو في عهد الحاسبات الكبيرة من أجل تخصيص Customize نظم برمجية واسعة النطاق Large Scale لتلبية طلبات محددة لعملاء معينين، واستخدت أيضا عبر فريق عمل أحد العملاء من أجل تلبية احتياجات موظفيه عبر بناء نسخ محددة من نظم تشغيل مصنع الكمبيوترات Manufacturer-الذي قد اشتراها هذا العميل-. وعلى سبيل المثال، فقد سبق فعل ذلك، مع مبرمجي النظم الذين كانوا يعملون لشركة آي بي إم، وبشكل أكثر تحديدا، كانوا يعملون على نظام مراقبة المحادثات/ النظام الافتراضي CMS/VM، وعلى نظام «معالجة المعاملات بشكل لحظي Real Time»، وعلى نظام «التحكم في بيانات العملاء»، وعلى ACP/TPF، وهو نظام مالي إداري -خاص بخطوط الطيران- بدأ في السبعينات وما زال يقوم بتشغيل نظم عالمية كبرى للتوزيع GDS ونظم بطاقات الائتمان حتى يومنا هذا.
وكان من الممكن أيضا أن يتم استخدام قدرات الماكرو المعالجة Processing فقط بحيث يقوم المُجمع بتوليد كود مكتوب بلغات مختلفة تماما، وعلى سبيل المثال، يمكن استخدام تلك التقنية في توليد نسخة من البرنامج مكتوبة بلغة كوبول عبر استخدام مجمع مزود ببرنامج ماكرو يحتوي على سطور من كود الكوبول، وأثناء وقت التجميع يمكن لمعاملات Operators أن توجه المُجمع لتوليد الكود بشكل تحكمي Arbitrary.
ويرجع سبب ذلك، كما تم إدراكه في السبعينات، أن مفهوم «معالجة الماكرو» Macro Processing يختلف عن مفهوم التجميع، حيث يشير المصطلح الأول في لغتنا الحاسوبية الحديثة إلى إمكانيات في برامج معالجة الكلمات، معالجة النصوص، أكثر من إشارته إلى توليد الكود. وحقيقة، فإن مفهوم «معالجة الماكرو» قد ظهر -وما زال يظهر- في لغة البرمجة «سي» C، حيث تدعم «تعليمات ما قبل المعالجة» Preprocessor Instructions من أجل تحديد قيم المتغيرات Set Variables. لاحظ أنه على عكس الأنواع المحددة لمعالجات الماكرو التي تم ذكرها والتي تعمل داخل المُجمعات، فإن المعالج القبيل للغة الـ C لم يكن Turing-Complete (متكامل مع معايير تورنغ) لنقص إمكانية «الدوارات» Loops أو الذهاب إلى تعليمة محددة عبر أمر Go To.
وبالرغم من قوة معالجة الماكرو، فقد تم إهمالها في اللغات عالية المستوى، بينما تظل مهمة وموجودة في المُجمعات Assemblers.
وذلك يرجع إلى الحيرة والارتباك التي وقع فيهما العديد من المبرمجين، حيث شكل لهم «تعويض معاملات» الماكرو مشكلة، ولم يستطيعوا فك الخلط بين معالجة الماكرو أثناء التجميع وأثناء التنفيذ.
ويتم استبدال معاملات الماكرو Parameter Substitution بشكل صارم عبر الاسم فقط: في وقت معالجة الماكرو، يتم استبدال قيمة المعامل باسم المعامل نصيا.وينتج أشهر صنف من الأخطاء Bugs عبر استخدام المعامل والذي كان يعبر -نفسه- عن Expression وليس عن اسم بسيط، في حين أن كاتب الماكرو يتوقع اسما Name.وفي الماكرو :
foo: macro a
load a*b القصد هنا هو أن يقوم المنادي Caller بتوفير اسم للمتغير، ويتم ضرب المتغير «العالمي» Global أو الثابت "b" في "a".إذا تم استدعاء foo مع المعامل a-c، سيقوم الماكرو بالتوسع بشكل غير متوقع.
ولتجنب هذا الأمر، تعلم مستخدمو «معالجة الماكرو» أن يقوموا بحصر المعاملات داخل تعريفات الماكرو Macro Definitions، ثم يكون على المناديين Callers أن يفعلوا المثل مع معاملاتهم «الحقيقية» Actual Parameters.
وقد قدمت لغات الـ PL/I وC ميزة الماكرو، لكن هذه الميزة كانت خطرة ولم تستخدم بشكل كافي لأنها لم تكن تعالج سوى النصوص. ومن ناحية أخرى، حافظ لغات الذكاء الصناعي Homoiconic مثل Lisp وProlog وForth على إمكانيات ماكروهات لغات التجميعات خاصتها، لأنهم جميعا قادرين على معالجة الكود الخاص بهم مثلهم مثل البيانات.
دعم البرمجة المهيكلة
قامت بعض المُجمعات بإدماج عناصر البرمجة المهيكلة من أجل تكويد Encode تدفق التنفيذ. وأقرب مثال لهذا النهج كانت مجموعة ماكرو المسماة Concept-14, والتي اقترحت لأول مرة عن طريق الدكتور هـ.د.ميلز (مارس 1970), وتم تنفيذها عبر مارفين كيسلر في قسم الأنظمة الفيدرالية بـ آي بي إم، والتي مددت إمكانيات مجمع الماكرو من نوع S/360 بـ IF/ELSE/ENDIF وبلوكات أخرى للتحكم في التدفق Flow Control. وقد كانت تلك طريقة لخفض أو إزالة استخدام عمليات GOTO في كود التجميع، حيث أن عمليات الـ GOTO من العوامل الرئيسية التي تسبب في ما يسمى بـ «كود الإسباجتي» -الكود المتشابك والمتعقد- في لغة التجميع. وقد كانت هذه الطريقة مستخدمة ومقبولة على نطاق واسع في أوائل الثمانينات (والتي شكلت الأيام الأخيرة لاستخدام لغة التجميع على نطاق واسع، لم يعد الأمر كذلك الآن).
وقد تم تقديم تصميم غريب سمى A-Natural، وهو عبارة عن مجمع من نوع Stream-Oriented يعمل مع معالجات 8080/Z80 وصممته شركة Whitesmiths Ltd. (تلك الشركة التي طورت نظام التشغيل الشبيهة بيونيكس والمسمى Idris، والذي وصف بأنه أول مترجم تجاري للغة السي C). وقد صنفت اللغة كمجمع، لأنها كانت تعمل مع عناصر الماكينة «الخام» Machine Elements مثل كود التنفيذ Opcodes، المسجلات، ومراجع الذاكرة References؛ ولكنها أدرجت جملا تعبيرية Expression Syntax للإشارة إلى ترتيب التنفيذ. وقد قامت: الأقواس Parentheses، والرموز الخاصة الأخرى، بجانب الـ Constructs الخاصة بالبرمجة المهيكلة المعتمدة على بلوكات Blocks، قام كل ذلك بالتحكم في تتابع توليد التعليمات Instructions.وقد تم بناء لغة A-Natural لتصبح مترجما خاص بلغة الـ C، أكثر من بنائها لكي يتم استخدامها في البرمجة اليدوية، لكن جملها المنطقية Syntax أعجبت العديد من المبرمجين الذين عملوا بها وكتبوا بها برامج بالفعل.
وقد ظهرت الحاجة والطلب إلى مترجمات أكثر تعقيدا بعد أن انحدر تطوير البرمجيات باستخدام لغات التجميع على نطاق واسع. وعلى الرغم من ذلك، فإن تلك المُجمعات لا تزال تستخدم في بعض الحالات، والتي تحوي قيودا مفروضة على الموارد -وقت، نفقات..الخ- أو أن الخصوصيات Peculiarities المتعلقة بهندسة النظام -الخاص بالتطبيق الجاري تطويره- تمنع الاستخدام الكفؤ للغات البرمجة عالية المستوى.
التركيب النحوي
الأوامر
يتبع كل أمر من أوامر لغة التجميع التنسيق التالي:
[label] mnemonic [operands]
فيما يلي يصف هذا الدليل بعض التعليمات الخاصة بلغة التجميع لحاسوب انتل 32 بت x86
التعليقات
ومثلها مثل معظم لغات البرمجة الأخرى، تسمح لغات التجميع بإضافة تعليقات إلى الشيفرة المصدرية، وتتم تجاهل هذه التعليقات عن طريق «المُجمع» -أي لا تتم ترجمتها للغة الآلة-. تبدأ تعليقات لغة التجميع بالفاصلة المنقوطة "؛". ويعد استخدام التعليقات بشكل جيد مع شيفرة لغة التجميع أكثر أهمية من استخدام التعليقات مع اللغات عالية المستوى، لأنه من الصعب استنباط معنى ومغزى سلسلة تعليمات لغة التجميع عبر قراءة الشيفرة فقط دون تعليقات توضحها.
ويمكن لحسن استخدام تلك التسهيلات Facilities أن يبسط جدا من مشكلات عمليات التكويد والصيانة الخاصة بكود اللغات منخضفة المستوى وإذا دعت الحاجة لتغييره فإن من الصعب جدا قراءة كود لغة التجميع الخام الذي يتم توليده عبر المترجمات أو برامج فك التجميع، حيث يتكون من مجموعة تعليمات متراصة، بدون أي تعليقات، بدون أي رموز لها مغزى، وبدون أي تعريفات للبيانات.
مثال
برنامج "Hello World" بلغة التجميع (من موقع tutorialspoint)section .text
global _start ;must be declared for linker (ld)
_start: ;tells linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!', 0xa ;string to be printed
len equ $ - msg ;length of the string
استخدام لغة التجميع
نظرة تاريخية
تم تطوير لغة التجميع لأول مرة في الخمسينيات من القرن المنصرم، وقد تم الإشارة لتلك اللغات في هذا الحين على أنها «الجيل الثاني» من لغات البرمجة. وقد محت لغات الجيل الثاني الكثير من مشكلات منح الأخطاء Error-Prone ومشكلات استهلاك الوقت التي اتصفت بها لغات البرمجة من «الجيل الأول» التي تعاملت مع الأجيال الأولى من أجهزة الكمبيوتر. وقد حررت اللغات الجديدة المبرمجين من الكثير من الأمور المملة مثل تذكر الرموز الرقمية وحساب عناوين الذاكرة. وقد استخدمت تلك اللغات يوما ما وبشكل واسع في جميع أنواع البرمجة. وعلى الرغم من ذلك فقد استبدلت تلك اللغات بشكل واسع بلغات البرمجة عالية المستوى، في البحث عن المزيد من التحسين لـ «إنتاجية» العمل البرمجي. واليوم، تستخدم لغة التجميع بشكل رئيسي في: التحكم المباشر في العتاد، الوصول إلى تعليمات المعالج المتخصصة Processor Instructions، أو لمعالجة مسائل حاسمة تتعلق بالسرعة/الأداء Performance. ومن الأنظمة التي تستخدم عادة لغات التجميع، تجد: مشغلات الأجهزة Device Drivers، النظم المضمنة منخفضة المستوى، وأنظمة الوقت الحقيقي Real-Time.
وتاريخيا، فقد تم كتابة عدد كبير جدا من البرامج بشكل كلي باستخدام لغة التجميع. وقد تم كتابة بعض أنظمة التشغيل بلغة التجميع وبشكل حصري، حتى تم انتشار لغة السي C بشكل واسع في فترة السبعينات وأوائل الثمانينات. وتم كتابة العديد من التطبيقات التجارية باستخدام لغة التجميع كذلك، ومنها كميات كبيرة من برمجيات تم كتابتها بواسطة شركات كبرى لتعمل على الحواسب الكبيرة الخاصة المصنعة عبر شركة آي بي إم. وعلى الرغم أنه -في نهاية الأمر- قامت لغات كوبول وفورتران باستبدال معظم هذا العمل، إلا أن عدد كبير من المنظمات/الشركات حافظت على نظمها وبنيها التحتية المبرمجة عبر لغة التجميع حتى التسعينات، حيث عملت طول هذه الفترة بشكل جيد.
وقد اعتمدت معظم الحاسبات الدقيقة على كود مكتوب يدويا باستخدام لغة التجميع، بما في ذلك نظم التشغيل والتطبيقات الكبيرة وذلك لعدة أسباب. أولها أن تلك النظم حافظت على قيود شديدة على الموارد، فرضت خصوصية على الذاكرة Memory وعلى عرض بنية التطبيقات Architecture، وخفضت من نسبة الأخطاء Bugs التي تظهر أثناء عمل النظم. وربما كان الأهم من ذلك كله كانت الحاجة لوجود مترجمات للغة عالية المستوى من الدرجة الأولى First-Class، تكون مناسبة لاستخدام الحواسيب الدقيقة. وقد يكون هناك عاملا نفسيا قد لعب دورا أيضا: أن الجيل الأول من مبرمجي الحواسيب الصغيرة ظلوا يحتفظون بموقف الهواة Hobbyists والذي يمكن صياغته في العبارة: «الأسلاك والزرديات» Wires and Pliers -عبارة تشير إلى تمسك أولئك المبرمجين بالأسلوب الصعب للغة التجميع على الرغم من توافر أساليب أسهل مثل اللغات عالية المستوى-.
وفي اطار تجاري أكثر، فإن الأسباب الرئيسية لاستخدام لغة التجميع كانت: حجم Size أقل، مشكلات Overhead أقل، سرعة أعلى واعتمادية Reliability أعلى.
وكأمثلة نموذجية لبرامج كبرى كتبت بلغة التجميع في ذاك الوقت، تجد نظام التشغيل مايكروسوفت دوس، وبرنامج آي بي إم لمعالجة الجداول لوتس 1-2-3, وكذلك معظم الألعاب الشهيرة لعائلة الأتاري Atari 800 للحواسب المنزلية. وحتى في التسعينات، معظم ألعاب الفيديو من نوع Console تم كتابتها عبر لغة التجميع، بما في ذلك معظم ألعاب شركات Mega Drive/Gensis وشركة Super Nintendo لأنظمة الترفيه. ووفقا لبعض المطلعين داخل صناعة البرمجيات، فإن لغة التجميع كانت أفضل لغة حوسبة يمكن استخدامها من أجل أداء/سرعة عاليين لأجهزة سيغا ساترن -وهي أجهزة Console كانت تشتهر في مجال تطوير وبرمجة الألعاب-. وكذلك لعبة NBA Jam والتي ظهرت عام 1993 كلعبة من نوع Arcade ونالت شعبية كبيرة، تعتبر مثالا آخر. واعتبرت لغة التجميع هي لغة التطوير الأساسية على عدة منصات لوقت طويل، منها: كومودور 64، أتاري إس تي وكذلك حواسب المنزل من نوع إكس سبكتروم. وقد تسببت عدم كفاءة لغة البيسيك -في ذلك الوقت- في استمرار اعتماد تلك الآلات على لغة التجميع، لقد عاب البيسيك سببين: لم يوفر سرعة تنفيذ عالية مع هذه النظم، ولم يقدم تسهيلات كافية من أجل استخدام أفضل لإمكانيات العتاد الخاصة بتلك النظم. بعض الأنظمة، وعلى الأخص أميغا، لديها "بيئة تطوير متكاملة مع إمكانيات عالية لاكتشاف ومعالجة الأخطاء وإمكانيات "ماكرو"، مثل المُجمع المجاني ASM-One، مقارنة بإمكانيات برنامج مايكروسوفت فيجوال ستوديو (على الرغم من أن ASM-One يسبق مايكروسوفت فيجوال ستوديو من حيث وقت الإصدار).
وقد تم كتابة المُجمع VIC-20 عبر «دون فرينش» ونشرته شركة «فرينش سيلك».وقد تم كتابته في برنامج يبلغ من الحجم 1639 بايت فقط، مما يجعل صاحبه يعتقد أنه أصغر مجمع رمزي تم كتابته في التاريخ. ويدعم المُجمع نظم العنونة الرمزية والتعريفات الخاصة بسلاسل الحروف وسلاسل الرموز ذات النظام الـست عشري. ويسمح المُجمع أيضا بتعيرات العناوين Address Expressions والتي يمكن توحيدها Combined مع عمليات: الجمع، الطرح، الضرب، القسمة، Logical AND, Logical OR والمعاملات الأسية Exponentiation Operators.
الاستخدام الحالي
دائما ما كان هناك جدل حول فائدة وأداء لغة التجميع بالمقارنة بلغات البرمجة عالية المستوى. ومعروف أن لغة التجميع لها اطار محدد Niche تظهر فيه أهميتها؛ انظر أدناه. ولكن بصفة عامة، تدعي المترجمات Compilers الحديثة المثلى Optimized أنها تستطيع معالجة كود لغات البرمجة عالية المستوى وتستطيع تنفيذه Run بنفس سرعة تنفيذ الكود المكتوب يدويا بلغة التجميع، على الرغم من بعض الأمثلة العكسية Counter-Examples التي يمكن أن تنشأ. وتشكل زيادة تعقيد المعالجات الحديثة صعوبات متزايدة في كتابة كود فعال محسن يدويا Hand-Optimized.وعلاوة على ذلك، ولاستياء عشاق الكفاءة Efficiency، فإن زيادة أداء/سرعة المعالج تعني أن معظم وحدات المعالجة المركزية CPUs تظل خاملة Idle معظم الوقت، بسبب التأخيرات الناجمة عن اختناقات Bottlenecks يمكن التنبؤ بها Predictable مثل عمليات الإدخال/الإخراج I/O وعمليات الـ Paging.ذلك مما جعل العديد من المبرمجين يتوقفون عن اعتبار سرعة تنفيذ الكود الخام أمرا مهما.
وهناك بعض الحالات التي قد يختار فيها الممارسون استخدام لغة التجميع، مثل الحالات التالية:
عند الحاجة لبرنامج تنفيذي ثنائي Binary قائم بذاته Stand-Alone، بمعنى: برنامج يجب أن يتم تنفيذه بدون اللجوء إلى مكونات Components أو مكتبات مرتبطة بلغة برمجة عالية المستوى أثناء وقت التنفيذ؛ وربما يكون هذا الوضع هو الأكثر شيوعا.وهذه أنواع مدمجة Embedded من البرامج، والتي تقوم بتخزين جزء صغير فقط من الذاكرة ويقوم الجهاز Device بتنفيذ مهام ذات غرض واحد Single Purpose. من تلك الأمثلة، تجد: الهواتف، أنظمة الوقود/إشعال الوقود في السيارات، أنظمة التحكم في تكييف الهواء، أنظمة الأمن وأجهزة الاستشعار.
التفاعل المباشر مع العتاد، وعلى سبيل المثال في مشغلات الأجهزة Drivers ومعالجات الاعتراضات Interrupt Handlers.
استخدام تعليمات خاصة بالمعالج Processor-Specific، غير متوفرة للمترجم Compiler.ومن الأمثلة الشائعة على ذلك، تعليمة الدوران في اتجاه البت Bitwise Rotation، والتي تستخدم في العديد من خوارزميات التشفير.
عند الحاجة لتحسين شديد Extreme Optimization، ومثال على ذلك: في دوارة داخلية Inner Loop في خوارزمية تستهلك المعالج بشكل كثيف. ويستفيد مبرمجو الألعاب من الإمكانيات الخاصة بخصائص العتاد في تلك الأنظمة، مما يمكن ألعابهم لتعمل بشكل أسرع.
في حالة وجود نظام ذو قيود شديدة على الموارد Resource Constraints (مثال: الأنظمة المضمنة)، لذلك وجب استخدام كود مكتوب يدويا لتحقيق الاستفادة القصوى من الموارد المحدودة، ولكن ذلك يصبح أقل شيوعا مع انخفاض أسعار المعالجات وتحسن مستوى الأداء/السرعة.
في حالة عدم وجود لغة عالية المستوى -على سبيل المثال: على معالج خاص أو جديد-.
في كتابة برمجيات من نوع «الزمن الحقيقي» Real-Time والتي تحتاج توقيتا دقيقا واستجابات دقيقة Responses، مثل برامج المحاكاة، نظم الملاحة الجوية والمعدات الطبية. وعلى سبيل المثال، في نظام التحكم في الطيران من نوع Fly-by-Wire، يجب ترجمة القياس عن بعد Telemetry واتخاذ إجراءات على أساس هذا القياس في ظل قيود زمنية صارمة -في أجزاء ضئيلة جدا من الوحدات الزمنية-. ويجب على تلك الأنظمة أن تتخلص من أي تأخيرات لا يمكن التنبؤ بها والتي قد تنشأ عبر لغات البرمجة المترجمة Interpreted، أو عبر الجمع الآلي للقمامة Garbage Collection، عمليات الـ Paging، أو تعدد المهام بشكل وقائي Preemptive Multitasking. وعلى الرغم من ذلك، فإن بعض لغات البرمجة عالية المستوى تقوم بإدماج مكونات من نوع Run-Time وإدماج واجهات لنظم التشغيل OS Interfaces والتي يمكنها أن تسبب مثل هذا التأخير. وهنا يعتبر اختيار لغة التجميع أو أي لغة منخفضة المستوى Lower-Level اختيارا جيدا مما يعطي المبرمج وضوح Visibility أكبر وسيطرة أفضل على تفاصيل المعالجة Processing.
في حالة الحاجة إلى تحكم كامل في البيئة المحيطة Environment، في المواقف التي تتطلب اجراءات أمنية مشددة حيث لا يمكن أخذ أمر على أنه مفروغا منه Taken for Granted.
لكتابة فيروسات الحاسوب، برامج من نوع Bootloaders، مشغلات لأجهزة بعينها، أو لأشياء أخرى تعمل بشكل قريب من العتاد أو من نظام تشغيل مكتوب بلغة منخفضة المستوى.
لعمل هندسة عكسية لأكواد ثنائية موجودة، والتي قد تكون أو قد لاتكون كتبت بشكل أصلي عبر لغة برمجة عالية المستوى، وعلى سبيل المثال: في حالة اختراق Cracking حماية النسخة الخاصة ببرنامج محمي وله حقوق ملكية Proprietary Software.
عمل هندسة عكسية وتعديل ألعاب الفيديو (معروف أيضا باسم ROM Hacking)، والذي يمكن عمله عبر عدة تقنيات. والطريقة الأكثر استعمالا هي تبديل كود البرنامج على مستوى لغة التجميع.
كتابة كود يقوم بتعديل نفسه Selfmodifying، وتبرع لغة التجميع في مثل هذا الأمر.
كتابة برامج الألعاب والتطبيقات الأخرى التي تتضن حسابات رسومية Graphing.
كتابة برنامج لمترجم يقوم بتوليد كود تجميعي، وبالطبع سيكون كاتب (كتاب) هذا البرنامج من المتخصصين في البرمجة بلغة التجميع.
ومع ذلك، فإنه يتم تدريس لغة التجميع حتى يومنا هذا في معظم مناهج الهندسة الإلكترونية وعلوم الحاسب. على الرغم من أن هناك قلة قليلة من المبرمجين اليوم يعملون بشكل منتظم مع لغة التجميع بوصفها أداة تطوير، فإن المفاهيم المرتبطة بلغة التجميع لا تزال مهمة جدا. ومن تلك المواضيع الأساسية: الحساب الثنائي Binary Arithmetic، تخصيص الذاكرة Allocation، معالجة المكدس Stack، تكويد مجموعة الأحرف Character Set، معالجة المقاطعات Interrupts، وتصميم المترجمات، كل تلك الأشياء سيكون من الصعب جدا فهمها دون فهم كيفية عمل الكمبيوتر على مستوى العتاد.ولأن سلوك الكمبيوتر يمكن تعريفه عبر مجموعة التعليمات Instruction Set الخاصة به، فإن الطريقة المنطقية لتعلم مجموعة المفاهيم المرتبطة بهذا «السلوك» هي دراسة لغة التجميع. وتمتلك معظم الأجهزة الحديثة مجموعة تعليمات مماثلة. لذلك، فإن دراسة لغة تجميع واحدة تكفي لتعلم الآتي: (1) المفاهيم الرئيسية، (2) للتعرف على المواقف التي يكون فيها من المناسب استخدام لغة التجميع، (3) لمعرفة كيف يمكن توليد كود تنفيذي كفؤ من اللغات عالية المستوى.
التطبيقات العملية
غالبا ما يتم استخدام الكود المكتوب بلغة التجميع في نظام ROM عند تحميل النظام (BIOS على نظم PC المتوافقة مع IBM) - كلمة BIOS اختصارا لـ Basic Input Output System-.ويستخدم هذا الكود المكتوب بلغة منخفضة المستوى، مع أشياء أخرى، في تهيئة واختبار العتاد قبل تحميل نظام التشغيل، ويخزن ذلك الكود في الذاكرة من نوع القراءة فقط. وحالما تم الوصول لمستوى معين من تهيئة الجهاز، يتم الانتقال إلى تنفيذ كود آخر، وغالبا ما يكون مكتوبا بلغة عالية المستوى؛ لكن الكود الذي يتم تشغيله بعد الضغط على زر تشغيل الكمبيوتر Power Button غالبا ما يكون مكتوب بلغة التجميع. ونطبق نفس الشئ على معظم برامج التحميل Boot Loaders.
وتقوم معظم المترجمات بمعالجة لغات عالية المستوى إلى لغة تجميع أولا قبل الترجمة النهائية، وبذلك تتيح لكود التجميع التعرض لعمليات التصحيح والتحسين Optimization. وتوفر لغات البرمجة منخفضة المستوى نسبيا، مثل لغة السي C، بناء لغويا خاصا (تركيب نحوي) لدمج الكود المكتوب بلغة التجميع مباشرة في كود المصدر الخاص بها. ويمكن للبرامج التي تستخدم مثل هذه التسيهلات، كـ نواة لينكس على سبيل المثال، أن تبني تجريديات Abstractions عبر استخدام عدة لغات تجميع على كل منصة عتادة مختلفة Hardware Platform.ويمكن للكود النقال Portable الخاص بالنظام أن يستخدم المكونات الخاصة بكل معالج -للعمل مع مختلف المنصات- خلال واجهة موحدة.
وتعد لغة التجميع شيئا ذي قيمة كبيرة مع «الهندسة العكسية»، لأن العديد من البرامج يتم تداولها في صيغة لغة الآلة، وغالبا ما تكون ترجمة لغة الآلة سهلة في الترجمة إلى لغة التجميع ويختبر بعناية في هذا الشكل، أما تحويله إلى لغة عالية المستوى لهو أمر صعب للغاية. وتستخدم أدوات مثل «المفكك التفاعلي» Interactive Disassembler نفس التقنية على شكل واسع من أجل نفس الأهداف.
هناك أيضا الدموسين والذي يجعل من استخدام لغة التجميع حقلا فريدا له. فهناك العديد من المسابقات الخاصة التي تقيد المتسابقين بتقييد إبداعاتهم -من البرامج- إلى حجم صغير جدا (أمثلة: 256 بايت، 1 كيلو بايت، 4 كيلو بايت أو 64 كيلو بايت)، وبالطبع فإن لغة التجميع هي أمثل حل لتحقيق هذا الهدف. وعندما يكون الحفاظ على الموارد، وخاصة وحدة المعالجة المركزية للأنظمة التي تفرض قيودا على المعالجة، مثل النماذج السابقة لأجهزة أميغا وأجهزة Commodore 64, هنا تصبح البرمجة بلغة التجميع أمرا لا بد منه: حيث يتم كتابة كود التجميع «يدويا» ويتم إعداد تسلسل التعليمات عبر المبرمجين في محاولة لخفض عدد دورات وحدة المعالجة المركزية المستخدمة؛ لأن القيود المفروضة على وحدة المعالجة المركزية غاية في الصرامة، لدرجة أن كل دورة لوحدة المعالجة المركزية يحب وضعها في الحسبان. ومع ذلك، فإن الفضل يرجع لاستخدام مثل تلك التطبيقات والتي أتاحت نظما مثل Commodore 64 أن ينتج رسوميات ثلاثية الأبعاد 3D Graphics تعمل في نمط «الزمن الحقيقي» Real-Time، مع تأثيرات متقدمة Effects، وهو الإنجاز الذي قد يعتبر تحقيقه بعيد الاحتمال على أجهزة حديثة ومتطورة مع معالج 0.99 ميجا هيرتز.
المصطلحات ذات الصلة
عادة ما يطلق على «لغة التجميع» أو «لغة المُجمع» الأسماء التالية: assembly, assembler, ASM أو symbolic machine code.وقد أطلق عليها بعض المبرمجين من أجيال الحاسب الكبير IBM اسم BAL ويعود اختصار الاسم للجملة «لغة التجميع الأساسية» Basic Assembly Language.
ملاحظة: إطلاق اسم «مجمع» على «اللغة» هو بالطبع أمر مربك وغامض، لأن «المُجمع» هو البرنامج الذي يقوم بتحويل الكود المكتوب بلغة التجميع إلى كود الآلة Machine Code.وقد يرى البعض هذا الأمر على أنه خطأ، وينقصه الدقة. وعلى الرغم من ذلك، فإن ذلك اللفظ شاع استخدامه بين المتخصصين والكتاب على مدى عقود. وبشكل مشابه، قام مصمموا بعض أجهزة الكمبيوتر بإطلاق اسم «المُجمع» على «برنامج التجميع» الخاص بهم Assembly Program.
عند عمل المُجمع، فإن الخطوة الحسابية التي يقوم بها، والتي تتضمن كل عمليات معالجة الماكرو، تسمى بـ «وقت التجميع» Assembly Time.
يرجع المسمى «تجميع» إلى السنوات الأولى لظهور الكمبيوتر (راجع. الكود القصير short code، الكود السريع speed code).
المُجمع العابر Cross Assembler (انظر المترجم العابر Cross Compiler) تشبه وظيفته وظيفة المُجمع. لكن تم إطلاق هذا المصطلح عليه، للإشارة أن المُجمع يعمل على جهاز كمبيوتر مختلف، عن ذلك الذي سيتم تنفيذ الكود الناتج عليه: النظام المستهدف.ولأنه، في الوقت الحاضر، يتم كتابة المُجمعات بشكل «متنقل» Portable وبلغات عالية المستوى مثل لغة السي C، فإن المُجمعات الحالية لا تمت لذلك الموضوع بصلة. فأهمية المُجمع العابر تظهر بشكل جلي إذا احتاج النظام المستهدف Target System إلى إمكانية تشغيل «المُجمع» بنفسه. وهذا هو الحال عادة مع الأنظمة المضمنة الصغيرة. وكذلك، فإن أهم ملمح مميز للـ «مجمع العابر» هو أنه يوفر واجهات تسهل من نقل الكود إلى المعالج المستهدف Target Processor، بمعنى: أن يكون على ذاكرة وميضية أو ذاكرة القراءة فقط القابلة للبرمجة والمسح. ويقوم بتوليد صورة ثنائية Binary Image أو ملف من نوع Intel Hex بدلا من أن يقوم بتوليد ملف مستهدف Object File.
الـ «توجيه المُجمع» Assembler Directive، هو أمر يتم توجيهه إلى المُجمع. وقد تؤدي هذه الموجهات أي شيء، مثل إخبار المُجمع بأن يدمج مع البرنامج ملفات كود أخرى Source Files، أو يخبر البرنامج بتخصيص أماكن معينة في الذاكرة لتحمل بيانات ثابتة Constants.
قائمة بالمُجمعات الخاصة بمعمارية الحاسبات المختلفة
تحتوي الصفحة التالية على قائمة بأنواع مختلفة من المُجمعات التي تعمل مع هندسات/أبنية مختلفة من الحواسب، وتحوي القائمة معلومات مرتبطة بكل نوع من أنواع تلك المُجمعات:
قائمة بالمُجمعات Assemblers
مزيد من التفاصيل
لقد تم كتابة ما لا يقل عن عشرات من المُجمعات لكل كمبيوتر شخصي، حاسب كبير، نظام مضمن ولعبة كونسول Console Game، في الماضي والحاضر. ولمطالعة بعض الأمثلة، راجع قائمة المُجمعات.
وعلى أنظمة يونيكس، غالبا ما يطلع على المُجمع التقليدي اسم as، على الرغم من أنه ليس كيان واحد من الكود، لأنه يجري عادة كتابة مجمع جديد لكل بورت Port.وهناك العديد من إصدارات يونيكس تستخدم GAS.
لكل مجمع لهجة خاصة Dialect، داخل مجموعة من المُجمعات.وأحيانا، تستطيع بعض المُجمعات قراءة اللهجة الخاصة بمجمع آخر، وعلى سبيل المثال، يمكن لمجمع TASM من قراءة كود الـ MASM القديم، لكن العكس ليس صحيحا.ويمتلك مجمعي الـ FASM والـ NASM بناء لغوي متشابه، لكن كلا منهم يدعم مجموعة مختلفة من الماكرو مما يجعل من الصعب الترجمة من أحدهم للآخر. وبالطبع فإن الأساسيات تظل واحدة، لكن المميزات المتقدمة Advanced Features تختلف.
أيضا، يمكن للغة التجميع أن تكون منقولة Portable عبر عدة أنظمة تشغيل، وعلى وحدة معالجة مركزية واحدة. فاصطلاحات Conventions استدعاء الوظائف لا تختلف كثيرا بين أنظمة التشغيل المختلفة وأحيانا لا تختلف على الإطلاق، وببعض الحرص، يمكن الحصول على «نقالية» Portability في لغة التجميع، وعادة يتم ذلك عبر الربط مع مكتبة سي C والتي لا تتغير بين نظم التشغيل.
وعلى سبيل المثال، العديد من الأشياء داخل مكتبة لغة السي libc تعتمد على «ما قبل المعالجة» Preprocessor لتقوم بأشياء مرتبطة بنظام التشغيل OS-Specific، واشياء مرتبطة بلغة السي C-Specific، وتقوم بعمل ذلك للبرنامج قبل أن تبدأ في الترجمة Compiling.وفي واقع الأمر، فإن بعض الوظائف والرموز لا يمكن ضمان وجودها خارج الـ Preprocessor. الأسوأ من ذلك، أن حجم وترتيب البنيات Structs، فضلا عن حجم بعض أنواع من تعريف الأنواع typedefs مثل off_t، لا يوجد تعريف مثل هذه الاشياء في لغة التجميع -بدون مساعدة من ملف خارجي لتحديد هذه القيم Configure Script-، وتختلف حتى بين الإصدارات المختلفة من لينكس، مما يجعل من المستحيل أن يتم استدعاء وظائف من مكتبة السي libc بشكل نقال Portable، غير تلك التي تتعامل بشكل بسيط مع القيم الصحيحة والمؤشرات كمعاملات.ولمعالجة هذه المسألة، يقوم مشروع FASMLIB (مكتبة للمجمع FASM) بتوفير مكتبة نقالة للمجمع تعمل على منصات Win32 ولينكس، لكنها ليست كاملة بشكل كافي حتى الآن.
بعض لغات برمجة الحاسوب عالية المستوى، مثل لغة السي C ولغة «بورلاند باسكال» Borland Pascal، تدعم التجميع الداخلي Inline Assembly حيث يمكن دمج فقرات صغيرة نسبيا من كود التجميع داخل الكود المكتوب باللغة عالية المستوى.وغالبا ما تحتوي لغة البرمجة Forth على مجمعاً يستخدم في كلمات CODE Words.
ويستخدم العديد من الأشخاص نظم المحاكاة من أجل كشف وتصحيح أخطاء البرامج المكتوبة بلغة التجميع.
مثال يقوم بعرض كود المصدر الخاص بلغة التجميع
مثال على مجموعة مختارة من التعليمات (من أجل كمبيوتر افتراضي Virtual Computer) مع العناوين المقابلة في الذاكرة حيث يتم وضع كل تعليمة.هذه العناوين ليست ثابتة Static، انظر إدارة الذاكرة. ويقوم بمصاحبة كل تعليمة مولدة (عبر المُجمع) الكود النهائي Object Code والذي يتوائم مع هندسة الكمبويتر الافتراضي Virtual Computer's Architecture.
انظر أيضًا
محول برمجي
مفكك
المُجمع الدقيق
لغات برمجة منخفضة المستوى
قائمة لغات البرمجة
لغات برمجة
المراجع
لمزيد من المطالعة
«كتاب مجتمع التجميع ASM»، كتاب متوفر على الويب ويحتوي معلومات مفيدة عن الـ ASM، بجانب دروس تعليمية، وأمثلة للكود. By ASM Community
جوناثان بارتليت: البرمجة من الألف إلى الياء.دار بارتليت للنشر، 2994. ISBN 0-9752838-4-7ومتوافر أيضا على شبكة الإنترنت في صيغة PDF
روبرت بريتون: البرمجة باستخدام لغة التجميع MIPS.دار برنتيس هول للنشر، 2003. ISBN 0-13-142044-5
بول كارتر: لغة التجميع للحاسب الشخصي PC.كتاب مجاني، 2001.المصدر: شبكة الإنترنت
جيف دانتيمان: لغة التجميع خطوة بخطوة.دار وايلي للنشر، 2000. ISBN 0-471-37523-3
راندال هايد: فن لغة التجميع.دار «نو سكراتش» للطباعة، 2003. ISBN 1-886411-97-2تتوافر مسودات الكتاب على شبكة الإنترنت في صيغ PDF وHTML
بيتر نورتون، جون سوتشا، كتاب بيتر نورتون حول لغة التجميع لأجهزة الحاسب الشخصي من نوع IBM، دار برادي للكتب، نيويورك: 1986.
مايكل سينجر، PDP-11.البرمجة باستخدام لغة المُجمع، وتنظيم الآلة Machine Organization، دار جون ويلي وأبناؤه للنشر: نيويورك: 1980.
دومينيك سويتمان: انظر لـ MIPS وهو يعمل.مورجان كوفان للنشر، 1999.ISBN 1-55860-410-3
جون والدورن: مقدمة للبرمجة باستخدام لغة التجميع RISC.دار أديسون ويسلي للنشر، 1998. ISBN 0-201-39828-1
وصلات خارجية
كتاب الفلسفة «فن لغة التجميع» لراندال هايد، متوفر بصيغتي PDF وHTML
لغة الآلة للمبتدئين
مقدمة للغة التجميع
مجتمع الـ ASM، مصدر معلومات عن البرمجة باستخدام لغة التجميع ويحتوي كتابا للـ ASM
جدول الكود الخاص بلغة التجميع الخاصة بمعالجات Intel 80x86 (ورقة مرجعية)
البرمجة باستخدام لغة التجميع الخاصة بيونيكس
القواعد الرئيسية لتشغيل هندسة IMB z، دليل الحواسب الكبيرة لـ IBM الخاص بلغة الآلة وبالعمليات الداخلية.
مجمع IBM عالي المستوى، دلائل IBM للغة التجميع الخاصة بالحواسيب الكبيرة.
PPR: تعلم لغة التجميع
مقدمة لكتابة تطبيقات من نوع 32-bit باستخدام لغة التجميع x86
أمثلة على البرمجة باستخدام لغة التجميع
كتابة تطبيقات لويندوز باستخدام لغة التجميع
معلومات حول برمجة التجميع على لينكس
المرجع الخاص بمجموعة التعليمات للمعالج x86
دروس تعليمية للغة التجميع Iczelion's Win32
نصائح لتحسين كود التجميع، مارك لارسون
دليل NASM
كتابة الكود بلغة التجميع 8086, ف. آيه. سميت
برمجيات
مينوت-أو-إس MenuetOS، نظام تشغيل تم كتابته كلية باستخدام لغة التجميع 82/64 بت.
مجمع SB، يعمل مع معظم المعالجات/ المتحكمات من نوع 8 بت.
مكتبة GNU Lighting، وهي مكتبة تقوم بتوليد كود بلغة التجميع يعمل في وقت التشغيل، ومفيدة جدا للمترجمات من نوع Just-In-Time.
مجمع نيت-وايد Netwide
جو-اسم GoAsm، مكون مجاني من أدوات Go: يدعم برمجة ويندوز من نوع 32 بت و64 بت
أنظمة مضمنة
استحداثات متعلقة بالحواسيب في 1949
برمجة
تنفيذ لغات البرمجة
لغات التجميع
لغات برمجة أنشئت في 1949
لغات تجميع