[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-6-idarat-dhakira-yul-mstore-mload-muashir":3},{"article":4,"author":54},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":7,"meta_description":16,"focus_keyword":17,"og_image":18,"canonical_url":18,"robots_meta":19,"created_at":15,"updated_at":15,"tags":20,"category_name":34,"related_articles":35},"d9000000-0000-0000-0000-000000000106","a0000000-0000-0000-0000-000000000092","Deep EVM #6: إدارة ذاكرة Yul — mstore وmload ومؤشر الذاكرة الحرة","deep-evm-6-idarat-dhakira-yul-mstore-mload-muashir","إتقان إدارة الذاكرة في Yul: mstore وmload ومؤشر الذاكرة الحرة والتخطيط اليدوي ومنطقة الصفر وأنماط ترميز ABI الفعالة.","## مراجعة نموذج الذاكرة\n\nذاكرة EVM هي مصفوفة بايت خطية تتوسع عند الطلب. تبدأ فارغة وتنمو في أجزاء من 32 بايت. في Yul لديك كودا تشغيل أساسيان:\n\n- **mstore(offset, value)** — كتابة 32 بايت في الذاكرة عند الإزاحة\n- **mload(offset)** — قراءة 32 بايت من الذاكرة عند الإزاحة\n- **mstore8(offset, value)** — كتابة بايت واحد\n\nالتكلفة: 3 غاز لـ mload\u002Fmstore، بالإضافة إلى تكلفة التوسيع إذا كتبت أبعد من الحد الحالي.\n\n## مؤشر الذاكرة الحرة (0x40)\n\nSolidity يحتفظ بمؤشر عند الموضع `0x40` يشير إلى أول بايت ذاكرة غير مُخصص. عند العمل في Yul داخل Solidity، يجب عليك احترام هذا الاتفاق:\n\n```solidity\nassembly {\n    \u002F\u002F تخصيص 64 بايت\n    let ptr := mload(0x40)\n    \u002F\u002F استخدام الذاكرة المخصصة\n    mstore(ptr, value1)\n    mstore(add(ptr, 0x20), value2)\n    \u002F\u002F تحديث المؤشر\n    mstore(0x40, add(ptr, 0x40))\n}\n```\n\nإذا نسيت تحديث المؤشر، فإن Solidity قد يكتب فوق بياناتك عند التخصيص التالي.\n\n## منطقة الصفر (Scratch Space)\n\nأول 64 بايت (0x00-0x3f) محجوزة كمنطقة صفر في اتفاقية Solidity. يمكنك استخدامها بحرية في كتل assembly دون تحديث مؤشر الذاكرة الحرة:\n\n```solidity\nassembly {\n    \u002F\u002F منطقة الصفر — آمنة للاستخدام المؤقت\n    mstore(0x00, key)\n    mstore(0x20, slot)\n    let hash := keccak256(0x00, 0x40)\n}\n```\n\nهذا أرخص من تخصيص ذاكرة جديدة لأنه لا يوسع الذاكرة ولا يحتاج لتحديث المؤشر.\n\n## تخطيط الذاكرة اليدوي\n\nفي عقود Yul المستقلة (بدون Solidity)، أنت تتحكم بالكامل في تخطيط الذاكرة:\n\n```yul\n\u002F\u002F تخطيط مخصص:\n\u002F\u002F 0x00-0x1f: منطقة الصفر 1\n\u002F\u002F 0x20-0x3f: منطقة الصفر 2\n\u002F\u002F 0x40-0x5f: مخزن مؤقت للإرجاع\n\u002F\u002F 0x60+:     ذاكرة ديناميكية\n\nlet returnBuffer := 0x40\nmstore(returnBuffer, result)\nreturn(returnBuffer, 0x20)\n```\n\n## ترميز ABI الفعال\n\nSolidity يولد ترميز ABI آمن لكنه مكلف. في Yul يمكنك ترميز البيانات يدوياً:\n\n```solidity\nassembly {\n    \u002F\u002F ترميز استدعاء transfer(address,uint256)\n    let ptr := mload(0x40)\n    mstore(ptr, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n    mstore(add(ptr, 0x04), recipient)\n    mstore(add(ptr, 0x24), amount)\n    \n    let success := call(gas(), token, 0, ptr, 0x44, 0, 0)\n}\n```\n\nهذا يوفر الغاز الذي ينفقه Solidity على:\n- التحقق من الأنواع في وقت التشغيل\n- الحشو والمحاذاة التلقائية\n- التحقق من returndata\n\n## أنماط كتابة الأحداث\n\nكتابة الأحداث (LOG) في Yul:\n\n```solidity\nassembly {\n    \u002F\u002F emit Transfer(from, to, amount)\n    let sig := 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\n    mstore(0x00, amount)\n    log3(0x00, 0x20, sig, from, to)\n}\n```\n\n## مقارنة: Solidity مقابل Yul\n\n```solidity\n\u002F\u002F Solidity: ~800 غاز\nfunction transfer(address to, uint256 amount) external {\n    balances[msg.sender] -= amount;\n    balances[to] += amount;\n    emit Transfer(msg.sender, to, amount);\n}\n\n\u002F\u002F Yul: ~500 غاز\nfunction transfer(address to, uint256 amount) external {\n    assembly {\n        \u002F\u002F حساب فتحة المرسل\n        mstore(0x00, caller())\n        mstore(0x20, balances.slot)\n        let senderSlot := keccak256(0x00, 0x40)\n        let senderBal := sload(senderSlot)\n        \n        if lt(senderBal, amount) { revert(0, 0) }\n        \n        sstore(senderSlot, sub(senderBal, amount))\n        \n        \u002F\u002F حساب فتحة المستلم\n        mstore(0x00, to)\n        let recipientSlot := keccak256(0x00, 0x40)\n        sstore(recipientSlot, add(sload(recipientSlot), amount))\n        \n        \u002F\u002F الحدث\n        mstore(0x00, amount)\n        log3(0x00, 0x20,\n            0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,\n            caller(), to)\n    }\n}\n```\n\n## أخطاء شائعة\n\n1. **الكتابة فوق مؤشر الذاكرة الحرة** — نسيان تحديث 0x40 بعد التخصيص\n2. **اختلاط الإزاحات** — mstore يكتب 32 بايت، لذا الإزاحة التالية هي +0x20 وليس +0x01\n3. **تجاهل توسيع الذاكرة** — الكتابة في إزاحات عالية جداً تكلف غازاً تربيعياً\n4. **عدم تصفير الذاكرة** — الذاكرة المخصصة حديثاً مصفرة، لكن منطقة الصفر قد تحتوي بقايا\n\n## الخلاصة\n\nإدارة الذاكرة في Yul هي المهارة الأساسية لكتابة كود EVM فعال. فهم مؤشر الذاكرة الحرة ومنطقة الصفر وتخطيط الذاكرة اليدوي يتيح لك كتابة عقود أسرع وأرخص بكثير من مخرجات Solidity الافتراضية.","\u003Ch2 id=\"\">مراجعة نموذج الذاكرة\u003C\u002Fh2>\n\u003Cp>ذاكرة EVM هي مصفوفة بايت خطية تتوسع عند الطلب. تبدأ فارغة وتنمو في أجزاء من 32 بايت. في Yul لديك كودا تشغيل أساسيان:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>mstore(offset, value)\u003C\u002Fstrong> — كتابة 32 بايت في الذاكرة عند الإزاحة\u003C\u002Fli>\n\u003Cli>\u003Cstrong>mload(offset)\u003C\u002Fstrong> — قراءة 32 بايت من الذاكرة عند الإزاحة\u003C\u002Fli>\n\u003Cli>\u003Cstrong>mstore8(offset, value)\u003C\u002Fstrong> — كتابة بايت واحد\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>التكلفة: 3 غاز لـ mload\u002Fmstore، بالإضافة إلى تكلفة التوسيع إذا كتبت أبعد من الحد الحالي.\u003C\u002Fp>\n\u003Ch2 id=\"0x40\">مؤشر الذاكرة الحرة (0x40)\u003C\u002Fh2>\n\u003Cp>Solidity يحتفظ بمؤشر عند الموضع \u003Ccode>0x40\u003C\u002Fcode> يشير إلى أول بايت ذاكرة غير مُخصص. عند العمل في Yul داخل Solidity، يجب عليك احترام هذا الاتفاق:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F تخصيص 64 بايت\n    let ptr := mload(0x40)\n    \u002F\u002F استخدام الذاكرة المخصصة\n    mstore(ptr, value1)\n    mstore(add(ptr, 0x20), value2)\n    \u002F\u002F تحديث المؤشر\n    mstore(0x40, add(ptr, 0x40))\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>إذا نسيت تحديث المؤشر، فإن Solidity قد يكتب فوق بياناتك عند التخصيص التالي.\u003C\u002Fp>\n\u003Ch2 id=\"scratch-space\">منطقة الصفر (Scratch Space)\u003C\u002Fh2>\n\u003Cp>أول 64 بايت (0x00-0x3f) محجوزة كمنطقة صفر في اتفاقية Solidity. يمكنك استخدامها بحرية في كتل assembly دون تحديث مؤشر الذاكرة الحرة:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F منطقة الصفر — آمنة للاستخدام المؤقت\n    mstore(0x00, key)\n    mstore(0x20, slot)\n    let hash := keccak256(0x00, 0x40)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>هذا أرخص من تخصيص ذاكرة جديدة لأنه لا يوسع الذاكرة ولا يحتاج لتحديث المؤشر.\u003C\u002Fp>\n\u003Ch2 id=\"\">تخطيط الذاكرة اليدوي\u003C\u002Fh2>\n\u003Cp>في عقود Yul المستقلة (بدون Solidity)، أنت تتحكم بالكامل في تخطيط الذاكرة:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-yul\">\u002F\u002F تخطيط مخصص:\n\u002F\u002F 0x00-0x1f: منطقة الصفر 1\n\u002F\u002F 0x20-0x3f: منطقة الصفر 2\n\u002F\u002F 0x40-0x5f: مخزن مؤقت للإرجاع\n\u002F\u002F 0x60+:     ذاكرة ديناميكية\n\nlet returnBuffer := 0x40\nmstore(returnBuffer, result)\nreturn(returnBuffer, 0x20)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"abi\">ترميز ABI الفعال\u003C\u002Fh2>\n\u003Cp>Solidity يولد ترميز ABI آمن لكنه مكلف. في Yul يمكنك ترميز البيانات يدوياً:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F ترميز استدعاء transfer(address,uint256)\n    let ptr := mload(0x40)\n    mstore(ptr, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n    mstore(add(ptr, 0x04), recipient)\n    mstore(add(ptr, 0x24), amount)\n    \n    let success := call(gas(), token, 0, ptr, 0x44, 0, 0)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>هذا يوفر الغاز الذي ينفقه Solidity على:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>التحقق من الأنواع في وقت التشغيل\u003C\u002Fli>\n\u003Cli>الحشو والمحاذاة التلقائية\u003C\u002Fli>\n\u003Cli>التحقق من returndata\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"\">أنماط كتابة الأحداث\u003C\u002Fh2>\n\u003Cp>كتابة الأحداث (LOG) في Yul:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">assembly {\n    \u002F\u002F emit Transfer(from, to, amount)\n    let sig := 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\n    mstore(0x00, amount)\n    log3(0x00, 0x20, sig, from, to)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"solidity-yul\">مقارنة: Solidity مقابل Yul\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F Solidity: ~800 غاز\nfunction transfer(address to, uint256 amount) external {\n    balances[msg.sender] -= amount;\n    balances[to] += amount;\n    emit Transfer(msg.sender, to, amount);\n}\n\n\u002F\u002F Yul: ~500 غاز\nfunction transfer(address to, uint256 amount) external {\n    assembly {\n        \u002F\u002F حساب فتحة المرسل\n        mstore(0x00, caller())\n        mstore(0x20, balances.slot)\n        let senderSlot := keccak256(0x00, 0x40)\n        let senderBal := sload(senderSlot)\n        \n        if lt(senderBal, amount) { revert(0, 0) }\n        \n        sstore(senderSlot, sub(senderBal, amount))\n        \n        \u002F\u002F حساب فتحة المستلم\n        mstore(0x00, to)\n        let recipientSlot := keccak256(0x00, 0x40)\n        sstore(recipientSlot, add(sload(recipientSlot), amount))\n        \n        \u002F\u002F الحدث\n        mstore(0x00, amount)\n        log3(0x00, 0x20,\n            0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,\n            caller(), to)\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"\">أخطاء شائعة\u003C\u002Fh2>\n\u003Col>\n\u003Cli>\u003Cstrong>الكتابة فوق مؤشر الذاكرة الحرة\u003C\u002Fstrong> — نسيان تحديث 0x40 بعد التخصيص\u003C\u002Fli>\n\u003Cli>\u003Cstrong>اختلاط الإزاحات\u003C\u002Fstrong> — mstore يكتب 32 بايت، لذا الإزاحة التالية هي +0x20 وليس +0x01\u003C\u002Fli>\n\u003Cli>\u003Cstrong>تجاهل توسيع الذاكرة\u003C\u002Fstrong> — الكتابة في إزاحات عالية جداً تكلف غازاً تربيعياً\u003C\u002Fli>\n\u003Cli>\u003Cstrong>عدم تصفير الذاكرة\u003C\u002Fstrong> — الذاكرة المخصصة حديثاً مصفرة، لكن منطقة الصفر قد تحتوي بقايا\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"\">الخلاصة\u003C\u002Fh2>\n\u003Cp>إدارة الذاكرة في Yul هي المهارة الأساسية لكتابة كود EVM فعال. فهم مؤشر الذاكرة الحرة ومنطقة الصفر وتخطيط الذاكرة اليدوي يتيح لك كتابة عقود أسرع وأرخص بكثير من مخرجات Solidity الافتراضية.\u003C\u002Fp>\n","ar","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:32.249869Z","إتقان إدارة الذاكرة في Yul: mstore وmload ومؤشر الذاكرة الحرة ومنطقة الصفر وأنماط ترميز ABI الفعالة.","Yul إدارة ذاكرة EVM",null,"index, follow",[21,26,30],{"id":22,"name":23,"slug":24,"created_at":25},"c0000000-0000-0000-0000-000000000016","EVM","evm","2026-03-28T10:44:21.513630Z",{"id":27,"name":28,"slug":29,"created_at":25},"c0000000-0000-0000-0000-000000000020","Gas Optimization","gas-optimization",{"id":31,"name":32,"slug":33,"created_at":25},"c0000000-0000-0000-0000-000000000018","Yul","yul","بلوكتشين",[36,42,48],{"id":37,"title":38,"slug":39,"excerpt":40,"locale":12,"category_name":34,"published_at":41},"d0000000-0000-0000-0000-000000000617","طبقة التشغيل البيني لـ Ethereum: كيف تصبح 55+ سلسلة L2 سلسلة واحدة","tabaqat-altashghil-albaini-ethereum-55-l2-silsila-wahida","يملك Ethereum اكثر من 55 rollup من الطبقة الثانية، مما يجزئ السيولة وتجربة المستخدم. طبقة التشغيل البيني لـ Ethereum — الجمع بين الرسائل عبر الـ rollups والمتسلسلات المشتركة والـ based rollups — تهدف الى توحيدها في شبكة قابلة للتركيب واحدة.","2026-03-28T10:44:45.626845Z",{"id":43,"title":44,"slug":45,"excerpt":46,"locale":12,"category_name":34,"published_at":47},"d0000000-0000-0000-0000-000000000616","اثباتات ZK ما وراء الـ Rollups: استدلال الذكاء الاصطناعي القابل للتحقق على Ethereum","ithbatat-zk-ma-waraa-rollups-istidlal-dhakaa-istinaai-ethereum","اثباتات المعرفة الصفرية لم تعد مجرد اداة للتوسع. في 2026، يتيح zkML استدلال الذكاء الاصطناعي القابل للتحقق على السلسلة، وتنقل معالجات ZK المشتركة الحسابات الثقيلة خارج السلسلة مع التحقق على السلسلة، وانظمة الاثبات الجديدة مثل SP1 وJolt تجعل ذلك عمليا.","2026-03-28T10:44:45.621594Z",{"id":49,"title":50,"slug":51,"excerpt":52,"locale":12,"category_name":34,"published_at":53},"d0000000-0000-0000-0000-000000000593","EIP-7702 في الممارسة العملية: بناء تدفقات الحساب الذكي بعد Pectra","eip-7702-fi-almumaarasa-alamaliyya-binaa-tadaffuqat-alhisab-aldhaki-baad-pectra","يسمح EIP-7702 لأي EOA على Ethereum بالعمل مؤقتاً كعقد ذكي في معاملة واحدة. إليك كيفية تنفيذ المعاملات المجمّعة ورعاية الغاز والاسترداد الاجتماعي باستخدام البدائية الجديدة لتجريد الحساب.","2026-03-28T10:44:44.185251Z",{"id":13,"name":55,"slug":56,"bio":57,"photo_url":18,"linkedin":18,"role":58,"created_at":59,"updated_at":59},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]