بسم الله الرحمن الرحيم.
في هذا المقال سنتعرف على الحلقات التكرارية: while loop, do-while loop, for loop والحلقات المتداخلة (Nested Loops)، وسنتعلم كيفية التحكم فيها والفرق بين استخداماتها.
الحلقات التكرارية: تُستخدم لتنفيذ كتلة من التعليمات بشكل متكرر بناءً على شرط معين. هناك أنواع متعددة، وكل واحد يناسب حالة استخدام مختلفة.
1. حلقة while
تُستخدم عندما يكون التكرار معتمداً على شرط معين — وقد لا تُنفذ الحلقة على الإطلاق إذا لم يتحقق الشرط.
while (condition) {
// كود يُنفذ طالما الشرط صحيح
}
مثال
#include <stdio.h>
int main() {
int i = 1;
while (i <= 5) {
printf("Iteration %d\n", i);
i++; // زيادة i
}
return 0;
}
في while، يُفحص الشرط قبل كل دورة — إن لم يتحقق من البداية، لا تنفذ الحلقة إطلاقاً.
2. حلقة do-while
تشبه while، لكنها تنفذ الكود مرة واحدة على الأقل حتى لو كان الشرط غير محقق في البداية — يُفحص الشرط بعد تنفيذ الكود.
do {
// كود يُنفذ مرة واحدة على الأقل
} while (condition);
مثال
#include <stdio.h>
int main() {
int i = 1;
do {
printf("Iteration %d\n", i);
i++;
} while (i <= 5);
return 0;
}
ملاحظة: حتى لو كان
i = 6في البداية، سيُنفذ الكود مرة واحدة ثم يفحص الشرط.
3. حلقة for
تُستخدم عندما يكون عدد التكرارات معلوماً مسبقاً. تحتوي على 3 أجزاء:
- Initialization — التعريف الأولي للمتغير.
- Condition — شرط التوقف.
- Update — تعديل المتغير بعد كل تكرار.
for (initialization; condition; update) {
// كود يُنفذ أثناء كل تكرار
}
مثال
#include <stdio.h>
int main() {
for (int i = 1; i <= 5; i++) {
printf("Iteration %d\n", i);
}
return 0;
}
4. الحلقات المتداخلة (Nested Loops)
حلقة تكرار خارجية (outer-loop) تحيط بحلقة داخلية (inner-loop). الحلقة الداخلية جزء من جسم الحلقة الخارجية، وتدور دورة كاملة لكل دورة واحدة من الخارجية.
#include <stdio.h>
int main() {
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 2; j++) {
printf("Outer: %d, Inner: %d\n", i, j);
}
}
return 0;
}
الناتج: 3 دورات خارجية × 2 دورات داخلية = 6 أسطر.
التحكم في الحلقات
break
الخروج من الحلقة فوراً.
#include <stdio.h>
int main() {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break; // الخروج من الحلقة
}
printf("%d\n", i);
}
return 0;
}
الناتج: 1 2 3 4 — الحلقة توقفت عند 5.
continue
تخطي التعليمات المتبقية في التكرار الحالي والانتقال إلى التكرار التالي.
#include <stdio.h>
int main() {
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue; // تخطي التكرار
}
printf("%d\n", i);
}
return 0;
}
الناتج: 1 2 4 5 — الرقم 3 تخطى الطباعة فقط.
جدول المقارنة بين الحلقات
| الحلقة | متى تستخدم | الفحص | عدد التنفيذ |
|---|---|---|---|
while | التكرار بشرط متغير | قبل كل دورة | صفر أو أكثر |
do-while | يجب تنفيذ الجسم مرة على الأقل | بعد كل دورة | واحد أو أكثر |
for | عدد تكرارات معروف | قبل كل دورة | صفر أو أكثر |
كيف ستبدو الحلقات في الـ Assembly؟
استكمالاً للمقال السابق — الحلقات هي القفزات العكسية (Backward Jumps) في الـ disassembly:
البنية النموذجية
أي حلقة تتحول إلى:
loop_start:
; جسم الحلقة
inc [i] ; التحديث (i++)
cmp [i], 5 ; الشرط
jle loop_start ; قفزة للخلف طالما الشرط صحيح
القفزة للخلف (loop target) هي البصمة الواضحة التي تعرف بها الحلقة في الـ disassembly فوراً.
while مقابل do-while في الـ assembly
while: الشرط يُفحص قبل الجسم — القفزة الشرطية في بداية البنية.do-while: الشرط يُفحص بعد الجسم — القفزة في النهاية.
معلومة تحسين: بنية do-while أسرع للمعالج لأنها قفزة واحدة. لذلك عند التحسين (O2) قد يحوّل المترجم حلقة while إلى do-while (loop rotation) — أي أن الشكل النهائي في الـ assembly لا يطابق دائماً ما كتبته.
break و continue في الـ assembly
break→ قفزة للخروج النهائي من الحلقة.continue→ قفزة إلى الخطوة التالية (التحديث/الشرط) مباشرة.
مثال من تحليل malware
في عينات حقيقية ستصادف حلقات تفحص حرفاً حرفاً (كما في نصوص strlen أو خوارزميات فك التشفير) — وتبدو هكذا:
decrypt_loop:
mov al, [esi] ; قراءة بايت
xor al, 0x1F ; فك التشفير
mov [edi], al
inc esi ; التقدم
inc edi
cmp al, 0 ; نهاية النص؟
jne decrypt_loop
هذه الصورة الذهنية (قراءة ← معالجة ← تقدم ← فحص ← قفزة للخلف) ستخدمك كثيراً في تحليل الـ binaries.
تمرين عملي
- أعد كتابة مثال
forبصيغةwhileوالعكس، ثم قارن الـ assembly الناتج بـgcc -S— ستلاحظ أن المترجم يبني كليهما بنفس البنية. - جرب
gcc -O2 -Sعلى حلقة while — ولاحظ كيف قد تتحول إلى بنية do-while. - اكتب حلقة تفك تشفير بايتاً بايتاً (مثل المثال أعلاه) وافحصها في IDA/Ghidra — ستطابق البنية في قسم “كيف ستبدو”.