الدرس 3 من 8
تدفّق التحكّم من الأسمبلي
- 16 دقيقة
- 6 فحوص
- 3 تلميحات
- إلى المطلوب
هدف الدرس
المقارنة والقفزة بدل if والحلقة
الشرح
لا توجد في الأسمبلي جملة if ولا حلقة while، بل مقارنة ثم قفزة. فالأمر cmp a, b يقارن ويحفظ النتيجة في أعلام (flags) داخل المعالج، ثم تقرأ القفزة الشرطية التي بعده هذه الأعلام، فإمّا أن تقفز إلى عنوان (label) وإمّا أن يكمل التنفيذ إلى السطر التالي.
- القفزة
jgتقفز إن كان الأوّل أكبر، وjleإن كان أصغر أو يساوي. - القفزة
jeتقفز إن تساويا، وjneإن اختلفا. - القفزة
jmpتقفز دائمًا بلا شرط.
وهذه القفزات تقارن بالإشارة، أي تفهم أن العدد قد يكون سالبًا، ولها أخوات تقارن بلا إشارة مثل ja وjb. وأوّل ما تسأله أمام شفرة الأسمبلي: متى تقفز؟ والسبب أن المترجِم يضع غالبًا قفزة تتخطّى جسم if حين لا يتحقّق شرطها، فالقفزة تحمل الشرط المعاكس:
h: cmp edi, 10 jle .small mov eax, 1 ret .small: mov eax, 0 ret
فالقفزة jle .small تعني: إن كان x أصغر من عشرة أو يساويها فاذهب إلى .small وأرجِع 0، وإلا فأكمل إلى السطر التالي وأرجِع 1.
والحلقة قفزة إلى الخلف. في هذه الدالة يحمل eax المجموع ويحمل ecx العدّاد، والأمر xor eax, eax طريقة المترجِمات المختصرة لتصفير مسجّل، والأمر inc يزيد واحدًا. والقفزة jg .done تُخرجك من الحلقة حين يتجاوز العدّاد n، والقفزة jmp .top تعيدك إلى أوّلها:
loop_sum: xor eax, eax ; eax = 0 mov ecx, 1 ; ecx = 1 .top: cmp ecx, edi jg .done ; ecx > n add eax, ecx ; eax += ecx inc ecx ; ecx += 1 jmp .top .done: ret
وقبل أن تكتب، تأمّل ما تفعله الحلقة حين يكون n صفرًا أو سالبًا، فالحكم لشفرة الأسمبلي لا لاسم الدالة ولا لما تتوقّعه منها.
المطلوب
اكتب الدالة h(x) التي تُرجع 1 إذا كان x أكبر من عشرة وإلا 0، والدالة loop_sum(n) التي تكافئ شفرة الحلقة أعلاه في كل الحالات، بما فيها الصفر والأعداد السالبة.
الفحوص
6 فحوص- الدالة h تُرجع 1 لما فوق العشرة
- الدالة h تُرجع 0 للعشرة نفسها
- الدالة h تكافئ شفرة الأسمبلي على أعداد كثيرة
- الدالة loop_sum تجمع من 1 إلى n
- الدالة loop_sum على قيم أخرى
- الدالة loop_sum تُرجع 0 للعدد السالب كما تفعل الحلقة