انتقل إلى المحتوى الرئيسي
بلوكتشينMar 28, 2026

Deep EVM #7: الحلقات والشروط الفعالة من حيث الغاز في Yul

OS
Open Soft Team

Engineering Team

تدفق التحكم في Yul

Yul يوفر ثلاث بنى للتحكم في التدفق: if، switch، وfor. على عكس Solidity، لا يوجد else مباشر — تستخدم switch بدلاً من ذلك.

الحلقات في Yul

بنية for الأساسية

assembly {
    for { let i := 0 } lt(i, 10) { i := add(i, 1) } {
        // جسم الحلقة
    }
}

يتم ترجمة هذا إلى أكواد تشغيل:

  • تهيئة i := 0
  • فحص الشرط lt(i, 10) -> JUMPI
  • جسم الحلقة
  • التحديث i := add(i, 1)
  • JUMP للعودة إلى الفحص

كل تكرار يكلف: JUMP (8 غاز) + JUMPI (10 غاز) + LT (3 غاز) + ADD (3 غاز) = ~24 غاز كحد أدنى.

تحسين: العد التنازلي

assembly {
    // العد التنازلي أرخص بغاز واحد لكل تكرار
    for { let i := 10 } gt(i, 0) { i := sub(i, 1) } {
        // استخدم sub(i, 1) للفهرس المعتمد على الصفر
    }
}

لماذا أرخص؟ iszero(i) (3 غاز) مقابل lt(i, n) حيث n يحتاج PUSH إضافي.

فك الحلقات

إذا كان عدد التكرارات معروفاً في وقت الترجمة، يمكن فك الحلقة:

assembly {
    // بدلاً من حلقة 4 تكرارات (96+ غاز للتحكم)
    // فك يدوياً (0 غاز للتحكم):
    let sum := calldataload(0x04)
    sum := add(sum, calldataload(0x24))
    sum := add(sum, calldataload(0x44))
    sum := add(sum, calldataload(0x64))
}

التوفير: لا JUMP ولا JUMPI = توفير ~24 غاز لكل تكرار مُزال.

جداول Switch

switch في Yul هو أكثر كفاءة من سلاسل if/else المتعددة:

assembly {
    switch shr(224, calldataload(0))
    case 0x6d4ce63c /* get() */ {
        mstore(0, sload(0))
        return(0, 32)
    }
    case 0x60fe47b1 /* set(uint256) */ {
        sstore(0, calldataload(4))
        stop()
    }
    default {
        revert(0, 0)
    }
}

أنماط الشرط

تجنب الفروع عند الإمكان

العمليات الحسابية أحياناً تحل محل الشروط:

assembly {
    // بدلاً من:
    // if gt(a, b) { result := sub(a, b) }
    // else { result := sub(b, a) }
    
    // القيمة المطلقة بدون فروع:
    let diff := sub(a, b)
    let mask := sar(255, diff)  // 0x00..00 أو 0xff..ff
    result := xor(add(diff, mask), mask)
}

الحد الأقصى والأدنى بدون فروع

assembly {
    // max(a, b) بدون فرع
    result := xor(a, mul(xor(a, b), gt(b, a)))
    
    // min(a, b) بدون فرع
    result := xor(a, mul(xor(a, b), lt(b, a)))
}

تحسين حلقات التكرار على المصفوفات

assembly {
    let len := sload(arraySlot)
    mstore(0x00, arraySlot)
    let dataSlot := keccak256(0x00, 0x20)
    
    let sum := 0
    for { let i := 0 } lt(i, len) { i := add(i, 1) } {
        sum := add(sum, sload(add(dataSlot, i)))
    }
}

مقارنة الغاز: Solidity مقابل Yul

النمطSolidityYul
حلقة 10 تكرارات~400 غاز~280 غاز
if/else متداخل~50 غاز~35 غاز
switch 4 حالات~80 غاز~50 غاز
جمع مصفوفة~600 غاز~400 غاز

التوفير يتراكم بشكل كبير في الحلقات والعمليات المتكررة.

الخلاصة

الحلقات والشروط في Yul تمنحك تحكماً دقيقاً في تكلفة الغاز. العد التنازلي، فك الحلقات، جداول switch، والعمليات بدون فروع هي أدوات أساسية في ترسانة مطور EVM المتقدم. في المقالة التالية سنطبق هذه المفاهيم لبناء مبادل رموز كامل في Yul خالص.