أفكر كثيراً في طريقة كتابة برامج قصيرة بلغة التجميع بوصفها تدريبًا عقلانياً على التفكير القريب من العتاد، ولا أتعامل معها كمجرد كتابة تعليمات. أول ما أنصحه به لنفسي أو لغيري هو فهم استدعاءات النظام والنمط الذي يتبعه نظام التشغيل لمعالجة البرامج الصغيرة؛ هذا يُخفض الحاجة لطبقات إضافية. بعد ذلك أركز على استخدام السجلات بدل الذاكرة قدر الإمكان لتقليل تعليمات التحميل والتخزين. قواعد بسيطة تساعد كثيراً: الحفاظ على عدد السجلات المستخدمة، إعادة استخدام السجل نفسه لمهام متعددة متتالية، واختيار تعليمات أصغر حجمًا (مثل القفزات النسبية القصيرة) عندما تسمح الشروط.
عند كتابة وظيفة موجزة التي تحتاج لاستدعاء فرعي واحد أو اثنين أفضّل تجنب إطار النداء الكامل (stack frame) وأستخدم 'syscall' أو 'ret' مباشرة، مع توثيق واضح لكل خطوة لتعقب الأخطاء لاحقاً. أدوات مثل objdump وgdb وstrace تصبح حبيباتي عند التصحيح؛ تُمَكّن من رؤية ما يفعله كل بايت وكيف يتفاعل البرنامج مع نواة النظام. بهذه الطريقة يصبح التجميع ليس صعباً بل مُرضياً ومتحكماً للغاية.
أستمتع بالتركيز على الكود القليل، لأنه يجعلني أمارس ما تعلمته عن المعالج والأوبكود. أبني برنامجاً صغيراً بلغة التجميع عادةً هكذا: أُعرّف قسم التعليمات (مثل '.text')، أعلِن نقطة البداية (مثلاً 'global start' في x86)، ثم أكتب سلسلة تعليمات بسيطة تتعامل مع السجلات مباشرة. على لينكس x8664 أمثلة نموذجية تكون باستخدام syscall مباشرة: وضع رقم النظام في rax، والوسيطات في rdi، rsi، rdx ثم استدعاء 'syscall'. للحفاظ على صِغر الحجم أتحاشى الربط مع مكتبات كبيرة، وأستخدم خيارات ربط مثل '-nostdlib' أو '-s' لإزالة الرموز. أحياناً أستعمل حيلة 'call/pop' للحصول على مؤشر إلى نص ثابت داخل البرنامج بدل تعديل الجداول، وهذا مفيد لطباعة نص دون استخدام مساحات بيانات كبيرة. التجربة مع أدوات التفكيك والتحقق من البايتات تمنحني متعة خاصة، وتجعل كل بايت محسوباً.
أحتفظ بذكريات عن الأيام التي كنت أحاول فيها تقليص كل برنامج إلى أقل عدد ممكن من البايتات، وهذا التفكير يشرح كثيرًا كيف أقترب من كتابة برامج قصيرة بلغة التجميع.
أبدأ دائماً بتقسيم الفكرة إلى خطوات أساسية: ماذا يفعل البرنامج بالضبط؟ هل سيطبع رسالة؟ هل سيستقبل مدخلًا واحدًا ثم يخرج؟ معرفة الهدف تسمح لي بتحديد أقل مجموعة من نداءات النظام (system calls) أو العمليات اللازمة، لأن التعامل المباشر مع نداءات النظام غالبًا ما يلغي الحاجة إلى مكتبات كبيرة. بعد ذلك أحدد مجموعة التعليمات المتاحة في معمارية المعالج (مثل x8664 أو ARM) وأختار السجلات التي سأعتمد عليها لتجنب عمليات الضغط والإخراج غير الضرورية على الذاكرة.
أستخدم تقنيات عديدة للتحجيم: استغلال التعليمات ذات التأثير الجانبي (مثل xor لإلغاء سجل بدل mov صفر)، استبدال الحلقات بتفريع قصير عندما يكون ذلك ممكناً، واستخدام القفزات القصيرة أو العناوين النسبية لتقليل البايتات. كذلك أضع رمز الدخول بطريقة بسيطة مثل تعريف نقطة البداية 'start' واستخدام syscall مباشرة لخروج نظيف. أخيراً أُبسِط عملية البناء: استخدام مصمّم التجميع المناسب (مثل nasm أو gas)، ربط بأسلوب يدوي مع خيارات حذف الرموز وstrip، وفحص الناتج مع tools مثل objdump وhexdump. هذا الأسلوب عملي وممتع؛ لا شيء يضاهي رؤية ملف تنفيذي صغير جداً يعمل بكفاءة.
أجد متعة خاصة في تقليص الأخطاء عند كتابة برامج قصيرة بلغة التجميع، لأن كل تصحيح يجعلني أفهم المعالج أفضل. عند التعامل مع الأخطاء أستخدم أدوات بخطوتين: أولاً فحص البايتات الناتجة بواسطة 'objdump -d' و'hexdump' لأتأكد أن شكل الأوامر كما توقعت، ثم تشغيل البرنامج تحت 'gdb' أو محاكٍ مثل qemu لتتبّع السجلات خطوة بخطوة. هذا يسمح لي بأن ألاحظ أموراً مثل ترتيب البايتات (endianness) أو تأثير تعليمات معينة على مؤشرات الحالة. كما أؤكد دائماً أنني أتعامل مع استدعاءات النظام بالأرقام الصحيحة (مثلاً رقم الخروج عند الحاجة) وأني لا أعتمد على إطار عمل خارجي.
في النهاية، كتابة برنامج قصير بالتجميع تتطلب صبرًا وتكراراً: خطأ واحد بسيط قد يكسر كل شيء، لكن تصحيحه يمنحك ثقة وفهماً حقيقياً لكيفية عمل الحوسبة على أدنى مستوى.
أعرف أن البعض يتخوف من التجميع لأنه يبدو معقداً، لكنني أراه تدريبًا عمليًا على الانضباط في الكود. أستخدم نهجاً عملياً: أكتب نموذجاً أولياً بلغة عالية المستوى لأفهم المنطق، ثم أُعيد كتابة الأجزاء الحيوية في التجميع للحصول على تحكّم أفضل في الأداء والحجم. للأنظمة المُدمَجة مثلاً أستغني تماماً عن المكتبات وأتعامل مع سجلات الجهاز وناقلات الذاكرة مباشرة؛ أستخدم تحميلات مباشرة للثوابت و'branch' قصير عندما أمكن لتقليل البايتات. كذلك أهتم بمراعاة محاذاة الذاكرة وتنفيذ التعليمات في خطوط أنابيب المعالج لأن ذلك قد يؤثر على الأداء أكثر من حذف بضعة بايتات.
أحياناً أدمج تعليمات مُجمَّعة يدوياً مع أجزاء مُولَّدة من مترجم بلغة C باستخدام inline assembly أو ربط ثنائي؛ هذا يمكّنني من الاستفادة من إنتاجية اللغة العالية مع الحفاظ على النواة الحساسة بالسرعة أو الحجم باليد. النهاية تكون غالباً ملف صغير ومُحدد الغرض، وهذا يُشعرني دائماً بشيء من الإنجاز.
2026-02-15 07:53:58
6
View All Answers
Scan code to download App
Related Books
وسيم فوق العادة.. وحب بلغة الإشارة
Sam
0
363
تدور أحداث القصة حول "زين"، الشاب العربي الذي حباه الله بوسامة وجاذبية لا تُقاوم، لكنه يفتقر تماماً للمال والشهادات، مما يدفعه لخوض مغامرة الهجرة غير الشرعية عبر البحر ليصل إلى السواحل الإيطالية.
بمجرد وصوله، يصطدم "زين" بالواقع المرير: فهو لا يملك أوراقاً رسمية، ولا مأوى، ولا يتقن كلمة واحدة من اللغة الإيطالية أو الإنجليزية، مما يوقعه في سلسلة لا تنتهي من المفارقات الكوميدية الصارخة؛
رغم معاناته مع "حاجز اللغة" والاختلافات الثقافية الهائلة، تصبح وسامته الفائقة وطيبته العفوية هما "جواز سفره" السري. يجد زين نفسه محاطاً بفيض من الفتيات الجميلات اللواتي يحاولن مساعدته، والتقرب منه، وتعليمه اللغة
الحب لم يكن أبدًا بسيط، الحب دومًا معقد.
إنه مُعقد حتى في أفلام الرومانسية الكوميدية التي يعترف البطل للبطلة بأنه واقع في غرامها.
إنه مقعد حتى وأن التقيت شخصًا تدرك أنكما خلقتما لبعضكما، المختار التي نسبة اللقاء به نادرة سيكون هناك تعقيدات!
كانت مارال تدرك ذلك حينما عادت بعد ثلاثة سنوات من العاصمة لمدينتها الصغيرة، والتقت هاري الرجل الذي لازلت تحبه، وتعلم أنه لا يمكنه محاربة المشاعر التي يملكها لها، لكن كما يحدث دائمًا يوجد تعقيدات خاصًا في المدن الصغيرة حيث بصعوبة يمكنك الحصول على خصوصية حياتك لأن الجميع لديهم رأيك في أفعالك لأنهم لا يملكون شيئا أفضل ليفعلوه.
ادخل على مسؤوليتك الخاصة
تحذير!
تحذير!!
تحذير!!!
هذا ليس مجرد كتاب.
هذا خطيئة نقية، فاسقة ملفوفة في مخمل وتقطر شهوة.
مجموعة محرقة من الإيروتيكا الإدمانية الخطرة حيث كل صفحة ستتركك مبللة، نابضة، ويائسة للمزيد. هذه ليست قصص حب حلوة. هذه حكايات خام، ملتوية، تسرع ضربات القلب مليئة بالـ BDSM الشديد، السيطرة الوحشية، الخضوع الذي يقطع الأنفاس، والكثير من الجنس الخام الذي لا يرحم حتى تتحطم ملابسك الداخلية قبل أن تنهي الفصل الأول.
ستُربطين، وتُعذبين بلا رحمة، وتُضربين حتى يلمع مؤخرتك أحمر، وتُخنقين بينما تذوبين في النشوة، وتُنكحين بعمق وبقسوة شديدة حتى تنسين اسمك. توقعي كسول مبللة تقطر، قضبان سميكة نابضة، ألعاب شريرة، تبادلات قوة محظورة، ونشوات تحطمك من الداخل.
هذه المجموعة أكثر ظلاماً، أكثر بللاً، وأكثر فحشاً من أي شيء قرأته من قبل. كل قصة تقدم حرارة جديدة — وحوش مهيمنة مختلفة، خاضعات مرتجفات مختلفات، انحرافات مختلفة، طرق مختلفة لكسرك وجعلك تتوسلين.
إذا كنتِ ضعيفة القلب...
إذا كنتِ تتوردين خجلاً عند فكرة أن تُمتلكي، وتُستخدمي، وتُفسدي لغيرك...
أغلقي هذا الكتاب الآن.
لكن إذا كنتِ تتوقين إلى ذلك النوع من المتعة الذي يقترب من الألم...
إذا أردتِ أن تُفسدي، وتُبللي، وتُتركي متألمة تشتاقين للفصل التالي...
فالآن، اقلبي الصفحة يا عسل.
دعي هذه القصص تفسدك.
دعيها تمتلكك.
دعيها تنكح عقلك حتى تصبحين مبللة ويائسة.
هل سبق أن اتخذت قرارًا ظننت أنه قرارك، ثم اكتشفت لاحقًا أن عقلك هو من خدعك؟
هل تساءلت يومًا لماذا يخاف الناس من أشياء لا وجود لها، أو لماذا يصدقون إشاعة تتكرر، أو كيف تستطيع كلمة واحدة أن تغيّر مستقبل إنسان، أو كيف يمكن لثلاثة أصدقاء أن يعيدوا تشكيل شخصية كاملة؟
"قصص صنعت قواعد نفسية" ليس كتابًا يشرح علم النفس بالطريقة التقليدية، بل يأخذك إلى عالم من القصص المشوقة التي تبدو في بدايتها مجرد أحداث عادية، قبل أن تكشف في نهايتها عن قاعدة نفسية خفية كانت تتحكم في كل شيء منذ اللحظة الأولى.
في كل قصة ستلاحق الأدلة، وتعيش الصراع مع الشخصيات، وتحاول توقع النهاية... لكن المفاجأة الحقيقية ليست فيما يحدث للأبطال، بل فيما ستكتشفه عن نفسك.
قد تجد نفسك في طالب غيّرت كلمة واحدة حياته، أو في شخص صدّق كذبة لأنه سمعها كثيرًا، أو في إنسان قادته عاداته اليومية إلى النجاح أو الفشل دون أن يشعر.
هذا الكتاب لا يمنحك نصائح مباشرة، بل يترك القصص تقوم بالمهمة. ومع كل صفحة ستدرك أن كثيرًا مما اعتقدت أنه "طبيعتك" ليس سوى عادة، وأن كثيرًا مما ظننته "حقيقة" قد يكون مجرد وهم صنعه عقلك.
بعد أن تنتهي من القراءة، لن تنظر إلى الناس... ولا إلى نفسك... بالطريقة نفسها مرة أخرى.
فتاة متخصصة في إدارة نظم المعلومات (MIS)، تُجبر على زواج لا ترغب فيه، وبدلًا من الاستسلام أو المواجهة التقليدية تقرر التعامل مع الزواج كـ "منظومة عمل" أو "عقد رقمي" وتبدأ بذكاء شديد في دراسة وثيقة الزواج والالتزامات الاجتماعية لإيجاد ثغرات وخرق البنود بشكل منظم يجبر الطرف الآخر على الانهاء من قبله
ولكن ...............
أحب أن أبدأ بصورة ذهنية قبل الدخول في التفاصيل: أصف لغة التجميع كخريطة مفصّلة للمبنى الذي تبنيه بالكود.
أشرح للمبتدئين أولاً العناصر الأساسية بطريقة مرئية: السجلات مثل أدراج صغيرة تحمل أرقامًا، والذاكرة مثل رفوف كبيرة، وتعليمات التجميع كأوامر قصيرة تُنفّذ حرفيًا من قبل المعالج. أحب أن أُريهم مثالاً حيًا بسيطًا — ثلاث أو أربع تعليمات فقط — ثم أترجم سطرًا واحدًا من كود بلغة عالية المستوى إلى تجميع خطوة بخطوة، حتى يروا كيف تُترجم الحلقات والدوال إلى 'mov' و'add' و'call' و'ret'.
بعد ذلك أقدِّم أدوات عملية: محرر تجميعي، محاكي بسيط أو ديباغر يسمح لهم بالمشي بالتعليمات واحدة واحدة ومشاهدة تغيّر السجلات والذاكرة. أُشجِّع على كتابة برامج قصيرة جدًا كطباعة رقم أو حساب مجموع، ثم تتبّعها خطوة بخطوة. هذا يربط النظرية بالتطبيق ويسهل استيعاب فكرة أن التجميع ليس سحرًا بل وصف دقيق لعمل المعالج.
أنهي دائمًا بنصائح عملية حول كيفية التعلم: ابدأ بمفردات أساسية، استعمل أمثلة صغيرة، ولا تخف من الرجوع أحيانًا إلى تمثيل بصري للذاكرة أو إلى جدول تعليمات المعالج؛ ومع القليل من الصبر يصبح التجميع أداة قوية لفهم عمق البرمجيات.
هناك حقيقة مهمة أود توضيحها عن لغة التجميع وعلاقتها بتسريع أداء الألعاب: هي مفيدة، لكنها نادراً ما تكون الحل الأول في المشروعات الحديثة.
أذكر أياما كانت الفرق الكبيرة تختبئ في سطور التجميع لتحصل على كل دورة ساعة CPU ممكنة، خصوصاً في محركات الرسوميات القديمة أو على منصات محددة جداً. اليوم غالباً ما أبدأ بالملفات الكبيرة في 'C' أو 'C++' أو حتى 'Rust'، وأثق بمقدرة المترجمات على توليد كود سريع. ومع ذلك أرى أن استخدام التجميع يبقى مقبولا لمقاطع صغيرة جداً وحساسة للغاية: لووب حسابات فزيائية عميقة، تشفير أو فك ضغط بلغة الأداء، أو روتينات صوتية متخصصة على عتاد قديم.
أعمل دائماً على قياس الأداء أولاً قبل التفكير بالغوص في التجميع. تحسين الخوارزميات، تنظيم الذاكرة (SoA بدلاً من AoS)، وتقليل الحشو في الكاش غالباً ما يعطي قفزات أداء أكبر من كتابة بضع تعليمات تجميع. فإذا لم يكن هناك قياس واضح وأن التجميع حقاً يحل عنق الزجاجة، فأنا أفضّل الاعتماد على الكود العالي المستوى مع استخدام التعليمات المدمجة SIMD عبر intrinsics عندما أحتاج قوة منخفضة المستوى دون التضحية بالانتقالية والصيانة.
أذكر مرةً جلستُ أمام لوحة تطوير قديمة واحتجتُ لكتابة جزء صغير جداً من الشيفرة صريحاً بلغة الآلة، ومن تلك اللحظة فهمتُ لماذا بعض الوظائف تجبرك على تعلم لغة التجميع.
هناك وظائف تصنع برامج تشغيل الأجهزة (device drivers) أو تكتب بداية الإقلاع (bootloaders) أو تعمل على برمجة متحكمات من دون نظام تشغيل؛ هذه البيئات تتطلب تحكماً مباشراً بالسجلات، التعامل مع مقاطعات، وإعداد الستاك والذاكرة بطريقة دقيقة لا يمكن للّغة العليا دائماً أن تضمنها. كذلك، في عالم تهيئة الأداء العالي — مثل حلقات الرسوم في الألعاب أو خوارزميات الضغط أو فك التشفير — المطوّر قد يحتاج لإدخال تعليمات خاصة أو استخدام SIMD للوصول لزمن استجابة لا تتيحه المترجمات.
وأيضاً، إن اشتغلتُ على أمن الأنظمة أو الهندسة العكسية لل firmwares أو تطوير استغلالات الضعفات، فهم لغة التجميع يصبح ضرورة. لا أقول إنّك ستكتب كل المشروع بلغة التجميع، لكنّ معرفة كيف تترجم التعليمات إلى أوامر فعلية وكيف يتصرف المعالج تمنحك قدرة لا تُقدّر بثمن عند التعامل مع الأجهزة على مستوى منخفض. هذه التجارب العملية جعلت تعلم التجميع ملمحًا طبيعيًا في مساري، خصوصاً حين تريد السيطرة الحقيقية على العتاد.
أجد هذا الموضوع مشوِّقًا لأنّه يلامس قلب العلاقة بين الشفرة والحديد: عندما أقول إن أنظمة التشغيل تعتمد على لغة التجميع لتحسين الأداء، فأنا أعني أنها تحتاج إلى تحكّم دقيق جدًا في كل دورة ساعة وبت واحد.
أنا أستخدم أمثلة عملية: أجزاء مثل مدخل المقاطعات، وتحويل السياق بين العمليات، ونقطة الدخول للنظام (syscall) تعاملت معها يدويًا بلغة التجميع لأنّه هنا لا مجال لطبقات التجريد. التجميع يتيح اختيار تعليمات معينة، إدارة سجلات المعالج مباشرة، وإدراج تعليمات متزامنة أو حواجز الذاكرة (memory barriers) لا تستطيع المولدات الآلية للشفرة ضمان موضعها بدقة في كل حالة. كذلك، بعض الروتينات الحرجة مثل 'memcpy' أو خوارزميات التشفير تستفيد من تعليمات SIMD متخصصة، وأحيانًا كتابة تجميع مخصّص يعطيني تحسّنًا واضحًا في زمن الاستجابة.
لكنني لا أغفل نقطة التكلفة: التجميع أصعب للصيانة ويختلف من معمارية لأخرى، لذلك عادةً أكتب الجزء الأعظم بلغة عالية المستوى وأستخدم التجميع فقط في المواضع الحسّاسة لتحقيق أقصى أداء. هذه المعادلة بين الدقّة والأًلفة هي التي تجعل التجميع باقياً في نواة أنظمة التشغيل، على الأقل لأجزاء محددة.
ألاحظ كثيرًا أن المبتدئين في لغة التجميع يغامرون بلا خطة واضحة، فيبدأون بكتابة تعليمات واحدة تلو الأخرى ظنًا أن الأمور ستتضح لاحقًا.
أحد الأخطاء الكبرى هو تجاهل قواعد استدعاء الدوال (calling convention): يضعون القيم في سجلات وينسون أن بعض السجلات يجب حفظها أو استعادتها حسب الاتفاقية، فينتهي بهم الأمر إلى تحطيم سياق البرنامج. كذلك، لا يمنحون الاهتمام الكافي لإدارة الستاك—دفع واستدعاء واستعادة المتغيرات المحلية—فتنتج أخطاء متشابكة يصعب تتبعها.
خطأ آخر شائع هو التقليل من أهمية الـ alignment وendianness؛ يفترضون أن كل شيء سيكون مرتبًا كما في البيئة التي يستخدمونها، بينما اختلاف البنية يؤدي إلى بيانات معطوبة أو أداء سيئ. كما يستخفون بأدوات التصحيح: أحيانًا الحرص على تتبع كل تعليمات البرنامج باستخدام debuggers وdisassemblers يكشف أخطاء بسيطة، لكنهم يتجاهلون ذلك.
أحب دائمًا أن أقول إن التجميع يشبه تركيب ساعة ميكانيكية: كل سن صغير مهم، وإذا اعتنيت بتوثيق خطواتك وحفظ القواعد الأساسية، تصبح الأخطاء أقل وأسرع في الإصلاح. هذه النصائح البسيطة وفرت عليّ ساعات من البحث.
البرمجة لتطبيق مشاركة فيديوهات قصيرة تشبه بناء آلة صغيرة تجمع بين الفيديو، الشبكات، والذكاء البسيط؛ أحب أن أشرحها خطوة بخطوة بطريقة عملية.
أبدأ من الواجهة: في التطبيق المحمول يجب تمكين تسجيل سريع ومريح، مع أدوات قص سريعة وتأثيرات وخيارات صوتية. تقنية مهمة هي رفع المقطع بشكل مقطّع (chunked upload) أو استخدام بروتوكول قابل للاستئناف مثل tus، بحيث لو انقطع الاتصال يُستأنف دون فقدان العمل. على الجهاز أفضّل أن أقوم بضغط مبدئي بسيط (اختيار معدل بت مناسب، H.264 عادةً) لتقليل استهلاك البيانات وإعطاء تجربة سريعة.
في الخادم، أتصور خط أنابيب (pipeline) يبدأ باستقبال الملف المؤقت ثم وضع مهمة في طابور رسائل (مثل Kafka أو RabbitMQ). عاملات (workers) تقوم بإنشاء صيغ متعددة عبر FFmpeg — نسخ بدقات مختلفة، شرائح HLS/DASH، وصور مصغرة. تُخزن الملفات في تخزين كائنات مثل S3، وتُوزّع عبر CDN لتقليل زمن التحميل. البيانات الوصفية تُخزَّن في قاعدة بيانات علائقية (للعلاقات) مع كاش مثل Redis لسرعة الوصول.
الجزء الأذكى هو الخلاصة/الـfeed: أنظمة التوصية تجمع إشارات فورية (مشاهدة، لايك، مدة المشاهدة) وإشارات تاريخية لبناء نموذج ترتيب. أدمج قواعد للإبراز والتجديد (freshness) وقيود للخصوصية، وكذلك خطاطات للمحتوى الممنوع عبر فلاتر آلية ومراجعة بشرية. أختم بأن المراقبة (logs، metrics)، آليات التحجيم التلقائي وCI/CD أمران لا يقلان أهمية؛ بدونهم تنهار التجربة مع نمو المستخدمين، وأنا دائمًا متحمس لرؤية فيديو بسيط ينتشر بفضل هندسة سليمة.