Uploaded avatar of iHiD

إنه نوفمبر اللقيمات

@iHiD
منذ ما يقرب من 3 سنوات
فيديو

مقدمة

أهلًا بالجميع. مرحبًا بكم في نوفمبر. أتمنى أن تكونوا بخير.

كان أكتوبر شهرًا مزدحمًا للغاية. أطلقنا للتوّ تحسينًا كبيرًا على حلول المجتمع. صرنا نزيل التكرار بينها، فلا تظهر الحلول المتشابهة إلا مرة واحدة، وأضفنا خيارات ترتيب جديدة، وإمكانية البحث بالكود، وإذا ألقيت نظرة على C#، سترى أننا أضفنا أيضًا إمكانية التصفية حسب مفاهيم برمجية مختلفة. فيمكنك البحث عن حلول تستخدم إزاحة البتات أو الاستدعاء الذاتي أو أي شيء آخر يخطر ببالك. وسنطرح ذلك على مسارات أخرى خلال أسبوع المجتمع.

لكن لنركّز الآن على #12in23.

كان أكتوبر شهرًا مثيرًا للاهتمام، استكشفنا فيه اللغات كائنية التوجه، لكننا هذا الشهر سنأخذ الأمر بجدية تامة. سنركّز على لغات التجميع، وتحديدًا MIPS Assembly وx86-64 Assembly وWebAssembly. وكالعادة، سيرشدنا Erik عبر ما يجعل هذه اللغات مثيرة وفريدة.

الشارات

كالمعتاد، يمكنك كسب شارة Nibbly November بإتمام أي 5 تمارين في هذه اللغات. لدينا أيضًا شارة العام الكامل التي أعلم أن كثيرًا منكم يسعى إليها. ولأجلها أعددنا لكم 5 تمارين مختارة لإتمامها. وهي:

  • Pop Count: عدّ البتات التي قيمتها 1 في عدد
  • Grains: احسب عدد الحبات على رقعة شطرنج تتضاعف خاناتها
  • Resistor Color: حوّل لون نطاق المقاومة إلى تمثيله الرقمي
  • Rotational Cipher: نفّذ الشيفرة الدورانية (المعروفة أيضًا بشيفرة قيصر)
  • Nucleotide Count: احسب عدد المرات التي تظهر فيها كل نيوكليوتيدة في سلسلة نصية من DNA

الخلفية

لماذا هذه التسمية Nibble November؟

حسنًا، كما تعرف على الأرجح، الـ byte يساوي 8 بتات، والـ nibble يساوي 4 بتات. تبدأ التسمية تتضح إذا غيّرت حرف y في كلمة byte إلى i، فتحصل على bite. وعندها يكون الـ nibble قضمة صغيرة.

ما هي لغة التجميع؟

حسنًا، لنبدأ ببعض الأساسيات. ينفّذ المعالج تعليمات، مثل "اجمع عددين" أو "أزح البتات إلى اليسار"، وهكذا. تُعرف هذه التعليمات بتعليمات الكود الآلي، وهي ليست سوى متتاليات محدّدة من البتات. وتنفيذ برنامج ما هو "ببساطة" (والكلمة بين علامتَي اقتباس) قيام المعالج بمعالجة متتاليات البتات هذه وتنفيذها.

ولأن كتابة التعليمات مباشرة كمتتاليات من البتات أمر مرهق وعرضة للخطأ، ابتكر Kathleen وAndrew Donald Booth لغة أقرب إلى الإنسان لتمثيل تعليمات الكود الآلي، وذلك في عام 1947. وتُسمى اللغة التي تمثّل تعليمات الكود الآلي لغة تجميع. ثم تُحوَّل لغة التجميع هذه إلى تعليمات كود آلي عبر "المُجمِّع".

ومن الجوانب المثيرة في لغات التجميع أنها مرتبطة ارتباطًا مباشرًا بمعمارية المعالج، مع أنها عادةً مستقلة عن نظام التشغيل.

بالمناسبة، إن كنت تتذكر البطاقات المثقّبة، تلك القطع الكبيرة من الورق المقوّى التي استُخدمت في أوائل الحواسيب لتنفيذ البرامج، فهي أيضًا كانت لغة تجميع!

كيف تختلف لغة التجميع عن اللغات التي نبرمج بها اليوم؟

الفرق الجوهري هو أن لغات التجميع منخفضة المستوى جدًا. ستفقد الكثير من التجريدات التي اعتدت عليها. لن تجد أي أصناف أو كائنات. الحلقات؟ سيكون عليك كتابتها يدويًا عبر القفزات. الدوال؟ لا وجود لها! وجدت أن كتابة كود التجميع تعلّمني التواضع، إذ تدرك حينها كم تسهّل اللغات الحديثة حياتك. لكن كتابة كود التجميع مفيدة أيضًا إلى حد بعيد، لأنك ستكتسب فهمًا أفضل بكثير لكيفية عمل الأشياء فعليًا.

معلومة طريفة: 99% من الكود المصدري للعبة RollerCoaster Tycoon كان كود تجميع مكتوبًا يدويًا! إنه إنجاز مذهل، وستقدّره أكثر بعد أن تجرّب كتابة بعض التجميع بنفسك.

هل ما زال الناس يكتبون بلغة التجميع؟

حسنًا، أقل مما كانوا يفعلون سابقًا. كان التجميع المكتوب يدويًا يتفوّق غالبًا على الكود الآلي الذي يولّده المترجم (وهذا أحد أسباب سماح لغة C++ بتضمين كود التجميع مباشرة)، لكن المترجمات أصبحت بارعة جدًا في توليد الكود الآلي لدرجة أن هذا نادرًا ما يصدق اليوم. ومع ذلك، ستجد لغة التجميع ما زالت مستخدمة في البيئات الحرجة الأداء أو المحدودة الموارد.

نظرة عامة

MIPS

  • MIPS (Microprocessor without Interlocked Pipelined Stages) هي عائلة من معماريات مجموعات التعليمات في الحواسيب ذات مجموعة التعليمات المختزلة (RISC)
  • طوّرتها شركة MIPS Computer Systems وأُصدرت أول مرة عام 1985
  • لها إصدارات عدة: MIPS I وII وIII وIV وV وMIPS32/64. كان الإصداران الأولان 32 بت فقط، لكن MIPS III قدّم دعم 64 بت.
  • امتدادات اختيارية عدة، مثل تعليمات SIMD والضغط
  • مؤثرة جدًا في معماريات RISC اللاحقة
  • أعلنت MIPS في عام 2021 أن معمارية MIPS لم تعد قيد التطوير وأنها انتقلت إلى RISC-V (وهي معمارية مفتوحة المصدر وبدون رسوم)
  • تُستخدم غالبًا في الأنظمة المدمجة (مثل أجهزة التوجيه) والخوادم (استخدمتها حواسيب Silicon Graphics، التي اشتُهرت باستخدامها في المؤثرات البصرية في الأفلام)، وفي الحاسوب العملاق NEC Cenju-4، وسيارة Tesla Model S، ومسبار New Horizons التابع لوكالة NASA، وكذلك لتدريس التجميع في الجامعات وفي عدة أجهزة ألعاب (مثل PlayStation الأصلي وPlaystation Portable وNintendo 64)

x86-64 Assembly

  • صمّمتها AMD وأُصدرت عام 1999 باسم معمارية AMD64
  • هي نسخة 64 بت من مجموعة تعليمات x86، التي يعود تاريخها إلى عام 1978 حين أطلقت Intel معالجها 8086. كان ذلك معالجًا 16 بت، لكن 80386 أضاف لاحقًا تعليمات 32 بت، وأصبحت تلك المجموعة من التعليمات مرادفة لـ x86.
  • الشيء الجوهري الذي أتاحه 64 بت هو عنونة ذاكرة أكبر (العنونة بـ 32 بت محدودة بـ 4 جيجابايت)، وقد صارت عنق زجاجة. نظريًا، يمكن لـ 64 بت عنونة 16 إكسابايت، لكن المستخدم حاليًا 48 بت فقط، ما يتيح عنونة 256 تيرابايت (ويمكن توسيعها لاحقًا عند الحاجة)
  • توسّع AMD64 مجموعة تعليمات x86، وصُمّمت لتكون متوافقة تمامًا مع التطبيقات الحالية 16 بت و32 بت عبر وضع توافق
    • كانت Intel قد صمّمت IA-64 دون مشاركة AMD. كانت مجموعة تعليمات 64 بت جديدة ومختلفة جدًا وغير متوافقة مع ما سبقها. وفي النهاية، انتصر AMD64 وطبّقت Intel نسختها الخاصة منه (بفروق دلالية طفيفة فقط)
  • تُستخدم في كل مكان. من محطات العمل إلى الخوادم (بما فيها الحواسيب العملاقة)، ومن الأنظمة المدمجة إلى أجهزة الألعاب (مثل PS5 وXbox Series X).

WebAssembly

  • صمّمها W3C، وهي هيئة معايير لتقنيات الويب
  • أهداف التصميم هي:
    • سريعة وآمنة وقابلة للنقل
    • تمثيل فعّال وقابل للنقل
  • في الأيام الخوالي، كانت سرعة التنفيذ على الويب تُحقَّق عادةً عبر إضافات متصفح متخصصة، مثل Flash وSilverlight، لأن JavaScript نفسها لا تناسب الحوسبة عالية الأداء كثيرًا. وكان أكبر عيوب هذه الإضافات أنها غالبًا ما كانت تعاني مشكلات أمنية كثيرة ولم تكن موحّدة المعايير.
    • صمّمت Mozilla لغة asm.js، وهي مجموعة فرعية من JavaScript تهدف إلى السماح بتشغيل الكود في المتصفح بأداء ممتاز، وقد حققت ذلك عبر ثبات الأنواع (دون تغيير الأنواع ديناميكيًا) وبلا جمع للقمامة. وبهذا أمكن للغات أن تُترجم إلى asm.js وتحصل على أداء جيد عند التشغيل على الويب. لكنها ظلت JavaScript، فكانت محدودة بما يمكن تحقيقه. ومن هنا جاء الاقتراح بلغة جديدة: WASM.
  • لغة شبيهة بلغة التجميع، بمعنى أنها توفّر مجموعة تعليمات يجب تنفيذها. والأهم أنها غير مرتبطة بمعالج بعينه، فهي مستقلة عن المنصة وتحتاج إلى تطبيق لكل منصة (آلة افتراضية). وهذا يعني أن WebAssembly في الحقيقة كود بايتي، لا كود آلي
  • أنواعها ثابتة (فرق جوهري عن JS)
  • تستخدم عادةً الترجمة المسبقة أو الترجمة اللحظية (لكن يمكن أيضًا تفسيرها)
  • معيار مفتوح يعرّف شيئين:
    • صيغة ثنائية
    • صيغة نصية (تُترجم إلى الصيغة الثنائية)
  • لها تطبيقات في جميع المتصفحات الرئيسية
  • تُستخدم في صفحات ويب كثيرة تتطلب أداءً عاليًا، مثل Google Earth وFigma وUnity وAutocad. وقد اكتسبت أيضًا انتشارًا في جانب الخادم، مثل تشغيل الخدمات المصغّرة، أو العمل على منصات SaaS (مثل CloudFlare workers) أو داخل Docker

ومن منظور البرمجة، كيف تختلف عن بعضها؟

MIPS

  • تستخدم معمارية تحميل-تخزين (وتُعرف أيضًا بسجل-سجل)، حيث تقوم التعليمات إما بالوصول إلى الذاكرة أو بالعمليات الحسابية، لكنها تعمل حصرًا على البيانات في السجلات

x86-64 Assembly

  • تستخدم معمارية سجل-ذاكرة، التي تتيح تنفيذ العمليات على (أو من) الذاكرة، وكذلك على السجلات

WebAssembly

  • تستخدم البرمجة القائمة على المكدس (بلا سجلات) مع إمكانية قراءة البيانات من الذاكرة وإليها

ما الذي يجعل هذه اللغات رائعة؟

MIPS

  • صغيرة. يمكن لمجموعة تعليمات MIPS أن تتسع كل تعليماتها في صفحة واحدة
  • اصطلاحات استدعاء راسخة تساعد على تحديد كيفية استخدام السجلات المتاحة، مثل أيّها يُستخدم لتمرير الوسائط وأيّها لإرجاع النتائج.
  • مستقرة. آخر إصدار صدر عام 2014
  • موثّقة على نطاق واسع، ولا سيما في النصوص الأكاديمية
  • استخدام واسع في الواقع. مليارات الأجهزة

x86-64 Assembly

  • مع كونها امتدادًا لـ x64، أُضيفت مزايا جديدة كثيرة، منها:
    • دعم الأعداد الصحيحة 64 بت
    • سجلات إضافية
    • تعليمات SSE (تعليمات متجهية)
    • الوصول النسبي إلى البيانات (أكثر كفاءة عند استخدام المكتبات المشتركة)
    • بت منع التنفيذ (ميزة أمنية تمنع تنفيذ الكود في صفحات معينة من الذاكرة)
  • مألوفة. ولأنها توسّع مجموعة تعليمات x86، سيكون تعلّمها سهلًا نسبيًا لمن يعرف مجموعة تعليمات x86 توثيق واسع ومفصّل
  • مستقرة. ومع أن إصدارات جديدة تُضاف بانتظام، يبقى جوهرها بالغ الاستقرار ومتوافقًا مع ما سبقه

WebAssembly

  • الآلة الافتراضية لـ WebAssembly القائمة على المكدس بسيطة وخفيفة مقارنة بلغات التجميع الخاصة بالمعالجات الفعلية (بما فيها RISC). وهذا يجعل الترجمة إليها سهلًا نسبيًا.
  • تستخدم صيغة WebAssembly النصية "سكرًا" على شكل تعبيرات S لتحقيق أسلوب أمري مألوف، ثم يُحوَّل ذلك إلى كود قائم على المكدس. وتُسمى الصيغة ذات تعبيرات S "الصيغة المسكّرة"، وهي "تُنزع سكرها" إلى الصيغة الأخرى المكافئة لما في الملف الثنائي. وستكون تعبيرات S مألوفة لكل من عمل يومًا مع LISP
  • توافق قوي مع JavaScript. تمرير البيانات من وإلى JavaScript سهل. مع تحفّظ مهم: لا تتيح WASM (حتى الآن) التفاعل مع DOM
  • تُحسَّن باستمرار. ولا تُحسَّن الآلات الافتراضية لـ WASM فحسب، بل المعيار نفسه أيضًا قيد التطوير النشط. وهناك أطنان من المزايا الجديدة قيد التصميم والعمل، مثل التعليمات المتعلقة بـ SIMD وجمع القمامة والخيوط وتحسينات استدعاء الذيل وغيرها
  • آمنة. يُتحقق من الكود وتُشغَّل في بيئة معزولة، ما يوفّر درجة أعلى من التحقق الساكن مقارنة بـ JavaScript أو لغات التجميع الأصلية. ودلالاتها محدّدة جيدًا، ما يسهّل فحصها والاستدلال عليها

أبرز المزايا

MIPS

  • الكفاءة. معالجات MIPS فعّالة جدًا، ما يجعلها ممتازة للأنظمة المدمجة.
  • الأداء. أداء رائع، ولهذا استُخدمت MIPS في الحواسيب العملاقة
  • سهلة التعلم. فمع تعليمات قليلة، وكل تعليمة تقوم بشيء واحد بسيط فقط، يصبح تعلّمها سهلًا. وممتازة لأغراض التدريس.

x86-64 Assembly

  • قوية. جرى تحسين x86-64 على مدى عقود، مع أطنان من التعليمات التي تساعد في الأداء. ومن أمثلة ذلك SIMD (تعليمة واحدة، بيانات متعددة)، وهي تعليمات يمكنها، حسنًا، تشغيل تعليمة واحدة على التوازي على بيانات متعددة.
  • منتشرة في كل مكان. فالأجهزة التي تشغّل x86-64 في كل مكان. ومعالجات Intel وAMD تطبّقها. وقد كانت المعيار الفعلي لفترة طويلة
  • تُحدَّث بانتظام. مثل تعليمات متجهية جديدة، مع SSE3-5 وAVX وAVX-512 وغيرها

WebAssembly

  • فعّالة. الصيغة الثنائية مدمجة ويمكن فك ترميزها والتحقق منها وترجمتها في تمريرة واحدة سريعة. وهي أيضًا قابلة للبث، ما يتيح بدء فك الترميز والتحقق والترجمة في أقرب وقت ممكن قبل رؤية كل البيانات. كما أنها قابلة للتوازي. وهذا يجعلها مثالية لتطبيقات الويب عالية الأداء.
  • هدف ترجمة ممتاز. يتيح تشغيل كود بلغات كثيرة على الويب. معظم اللغات الرئيسية تدعم الترجمة إلى ملفات WebAssembly الثنائية، ما يعني أن كودك يمكن أن يعمل على الويب دون الحاجة إلى كتابة JavaScript. وبعض اللغات لا تترجم كودك إلى WebAssembly، بل تترجم بيئة التشغيل إلى WebAssembly، التي يمكنها بعدها تشغيل كود بايتي دون تغيير.
  • سهلة النشر والتشغيل. كل ما تحتاجه آلة افتراضية قادرة على تفسير الكود البايتي، وجميع المتصفحات الرئيسية تتضمن واحدة.
  • غير مرتبطة بالويب، بل يمكنها العمل على جانب الخادم أيضًا. واجهة نظام WebAssembly (WASI) هي واجهة (ABI وAPI) مصمّمة لتكون قابلة للنقل إلى أي منصة. وهي شبيهة بـ POSIX (واجهات قياسية لأنظمة Unix) وتوفّر أشياء مثل الإدخال/الإخراج. والأمن جزء أساسي من تصميمها، ويشمل العزل والاعتماد على القدرات (عليك أن تطلب الأذونات صراحةً لأشياء مثل الملفات أو المقابس). ولـ WASI أيضًا إمكانية تسهيل التواصل بين اللغات. كتب Solomon Hykes، أحد مؤسسي Docker، في عام 2019: "لو كانت WASM+WASI موجودة في 2008، لما احتجنا إلى إنشاء Docker"

أيّها تختار

  • إن لم تكن قد عملت يومًا بلغة تجميع، فغالبًا WebAssembly هي أسهل لغة تبدأ بها. ومع ذلك، إن أردت تعلّم لغة تجميع تُترجم إلى كود آلي، فجرّب MIPS Assembly
  • إن كنت تعمل على جهاز x86-64 (وهو مرجّح جدًا)، فجرّب x86-64 Assembly
  • إن كنت تعرف LISP، فستقدّر أن WebAssembly تستخدم تعبيرات S
  • إن كنت تعمل على تطبيقات ويب، فWebAssembly هي الخيار الأكثر منطقية
  • إن كان الأداء يهمّك، فـ x86-64 وMIPS خياران رائعان. أو إن كان أداء الويب يهمّك، فجرّب WebAssembly
1 نوفمبر، 2023 · هل وجدته مفيدًا؟