• الإعلانات

    • فيصل الحربي

      تسجيل عضوية جديدة في المنتدى   01/31/2016

      السلام عليكم ورحمة الله وبركاته  عزيزي العضو الجديد :  حاليا رسالة الإيميل لتأكيد صحة إيميلكم تذهب للبريد العشوائي ( جاري حل المشكلة )  فإذا لم تجد رسالة التحقق من إيميلكم في صندوق الوارد لديكم إتجه للبريد العشوائي ( JUNK)  وقم بتفعيل إشتراككم من هناك   

هاني الأتاسي

المشرفين القدامى
  • عدد المشاركات

    1,220
  • تاريخ الانضمام

  • تاريخ اخر زياره

كل شيء نشر بواسطة هاني الأتاسي

  1. سلسلة - شغل مخك (5)

    إذا كنت بقارب وألقيت بشنطة بالماء هل سوف يرتفع مستوى الماء ؟؟ ;) ;) :P :P
  2. سلسلة - شغل مخك (6)

    #define bits(n) ((1<<n)-1) #define setbits(x, p, n, y) (x & ~(bits(n)<<p) | (y & bits(n))<< p)
  3. Windows In The Cloud

    تحياتي للفريق العربي للبرمجة .. يوم الاثنين ميكروسوفت أعلنت عن منتجها الجديد Windows Azure أو Opearting System on the Cloud وهو عبارة عن نظام تشغيل يعمل على مجموعة من الخدمات المتاحة في الأنترنت . وبشكل مبسط يتيح Windows Azure للمبرمجين من كتابة servics وتشغيلها من عليه وأيضا يتيح حفظ البيانات. من أهم الأمور التي يستفيد منها المطور من البرمجة في الcloud هو سهولة تضخيم الموقع scalability . كلنا يعرف ماذا يحدث إذا زاد ضغط الزوار على الموقع ، يبطئ الموقع أو في أسوء الحالات يتوقف عن العمل . في windows azure عندما يزداد عدد زوار الموقع او الخدمة ، فالنظام الجديد يقوم بتحميل برنامجك على أجهزة اخرى وتوزيع العمل عليها وبالتالي يستمر عمل الخدمة في أسوء الحالات . يمكنك البرمجة للcloud باستخدام asp.net ولغات .net . فيمكنك تصميم الويب او كتابة الخدمات بنفس الطريقة التي تقوم بها عند كتابة الويب بالشكل الطبيعي الآن . حاليا يمكنك كتابة نوعين من البرامج وهي webrole و workerrole . الأولى يمكنك أن تخدم فيها موقع asp.net او web service . أما الثانية فهي تعمل في الخلف وتقوم بمعالجة البيانات الممررة اليها . كمثال عليهما يمكنك أن تشبه ال webrole بموقع ال youtube و ال workerole بالمعالج الذي يحول الفيديو إلى صيغة الyoutube . ومن أجل تسريع عملية المعالجة يمكننا أن نهيئ برنامجنا من أن يشغل عدد معين من ال workerrole وبالتالي كل فيديو يتم معالجته على جهاز مختلف في نفس الوقت وبالتالي زيادة سرعة المعالجة. من أحد الأمور التي سوف تجدها مختلفة بعض الشئ هوكيفية التعامل مع البيانات . ففي الcloud لا يوجد sql server بالطريقة التي نعرفها اليوم . الأمر مختلف بعض الشئ ، فهناك ثلاث أنواع من البيانات : 1- queue: ويمكن استخدامها من اجل تبادل رسائل بين الroles .. مثلا ال webrole تبعث رسالة إلى ال workerrole من أجل اخبارها ببدأ معالجة شئ ما. 2- blob: يمكن استخدامها في حفظ بيانات كبيرة كالملفات. 3- table: وهي عبارة عن قاعدة البيانات التي يمكن أن يحفظ فيها data objects ويتم تعريفها عن طريقة كتابة class واستخدام linq من اجل ال queries .. حاليا يمكنك أن تنزل Windows Azure SDK وتستكشف كيف يمكنك بناء برامج تعمل على Windows Azure ، ومع الSDK ينزل محاكاة لبيئة Windows Azure حيث يمكنك كتابة برامج كاملة وتستخدم البيانات في جهازك كما أنك على البيئة الحقيقية . وأيضا باستخدام Windows Azure SDK for Visual Studio ، يمكنك استخدام Visual Studio في بناء برامجك و تشغيلها . هذه بعض الوصلات التي سوف تساعدك في استكشاف Windows Azure .. http://www.microsoft.com/azure/default.mspx http://blogs.msdn.com/cloud Day 1 Keynote - (stream) - A Lap Around Windows Azure - (stream) Developing and Deploying Your First Windows Azure Service - (stream) MSDN Windows Azure Forums
  4. سلسلة - شغل مخك (11)

    :D :D :D هي ياشباب .. حاولت أحل هذه المسألة وتوصلت إلى نتيجة مشابهة لأحد الاجابات السابقة .. بس طلعت هي سهلة ..:: اجابتي هي : void bitreverse(int &a) { a = a >> 16 | a << 16; a = (a & 0xff00ff00) >> 8 | (a & 0x00ff00ff) << 8; a = (a & 0xf0f0f0f0) >> 4 | (a & 0x0f0f0f0f) << 4; a = (a & 0xcccccccc) >> 2 | (a & 0x33333333) << 2; a = (a & 0xaaaaaaaa) >> 1 | (a & 0x55555555) << 1; } الفكرة جدا بسيطة وهي التالية : من أجل قلب بتات عدد من 32 بت مثلا هي عبارة عن قلب أول 16 بت مع ثاني 16 بت ومن ثم كل 16 بت يتم فلبها كالتالي : قلب 8 بت ب 8 بت و ال 8 يتم قلبهم 4 ب 4 و الأربعة يتم قلبها 2 ب 2 و أخيرا يتم قلب البتين .. في النهاية سوف نحصل على العدد المقلوب .. ممكن للطريقة السابقة أن تتم بصورة عكسية أيضا .. والكود السابق تماما يمثل الكلام الذي ذكرته .. حيث السطر الأول يقوم بقلب ال 16 بت و التاني يقوم من أجل كل 16 بت بقلب ال 8 بت وهكذا حتى السطر الاخير الذي يقوم بقلب كل بتين متجورين .. :)
  5. هناك العديد من الأخطاء في هذا الكود صديقي ... أولا : يجب عليك في البداية استدعاء التابع WSAStartup الذي يقوم بتحميل مكتبة ال Windsock أو Ws2_32.dll في الذاكرة .. ومن ثم كان عندك خطأ في تعليمة ال printf ...!؟!؟!!؟!؟ ومن ثم لا تنسى اضافة المكتبة ws2_32.lib في خصائص المشروع كالتالي .. إذهب إلى Project ثم Setting .. اختر All configuration في ٍSettings for . اختر المدخل Link على اليمين . ثم أضف النص Ws2_32.lib إلى Object/library modules .. الكود الجديد هو ... انسخ الكود #include <stdio.h>#include <winsock.h>  #define DEST_IP "64.212.171.241"#define DEST_PORT 6667 void main(){ SOCKET sockfd; struct sockaddr_in dest_addr; // will hold the destination addr  WORD wVersionRequested; WSADATA wsaData; int err;  wVersionRequested = MAKEWORD( 2, 2 );  err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { printf("could not find a usable WinSock DLL.n"); return; }  __try { sockfd = socket(AF_INET, SOCK_STREAM, 0); // do some error checking!  dest_addr.sin_family = AF_INET; // host byte order dest_addr.sin_port = htons(DEST_PORT); // short, network byte order dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); memset(&(dest_addr.sin_zero), ' 
  6. أخي آسف على التأخير .. سوف أعطيك لمحات بسيطة ولكن جدا مفيدة إلى أن ألاقي وقت أفصلك أكثر أو أحد من المنتدى يقوم بذلك عني أو أنت تقوم بذلك :) أولا من أجل القيام بعمل برنامج شبكة . طيعا أنت تعلم أنت تحتاج إلى برنامجين واحد اسمه server سوضع في الجهاز المركزي . والآخر client وهو يوضع في الجهاز الطرفي .. أيضا طبعا تحتاج إلى عنوان جهاز ال server مثلا رقم ال ip وال port المستخدم .. بالنسبة لل client فإن الكود في الأعلى يقوم بعملية الربط مع ال server وتهيئة الجهاز الطرفي من أجل ارسال واستقبال البيانات .. يمكن أن تضيف وبكل سهولة تعليمات الارسال والستقبال إلى الكود في الأعلى وهم write من أجل الارسال و read من أجل الاستقبال .. هذان جدا متشابهان حيث تحدد قيمة ال socket المتوح ومؤشر إلى الذاكرة وعدد البايتات التي سوف تستخدمها .. مثال : انسخ الكود char buffer[250]; strcpy(buffer, "test); write(sockfd, buffer, 250); read(sockfd, buffer, 250);  بالنسبة لل server .. تستخدم bind عوضا عن connect وذلك لفتح ال socket في السيرفر حيث bind تقوم بعمل socket طرف نهائي فقط أي في السيرفر فقط . أي لا تحدد رقم ال ip للجهاز الطرفي بل تحدد ال ip للجهاز نفسه .. وبعد bind يجب أن ينتظر الserver من ال client ارسال أي من المعلومات وهذا الانتظار يتم عن طريق listen وهي مثل getch في السي أي لا ترجع قيمة حتى يتصل أحد ال client .. وبعدها تستخدم accept من أجل الموافقة على طلب ال client ومن ثم تستخدم read و write كما في السابق ... وشكرا .. :)
  7. سلسلة شغل مخك - العودة - 1

    معظمكم يعرف سلسلتي شغل مخك في أيام الخوالي .. أحببت أن أعيدها وأقدم أسئلة أقوى وبتحدي أكبر :) الحلول ممكن أن تكون بأي لغة سي ، سي++، سي# ، psuedo code ، ... أبدأ الجزء الثاني من السلسلة بهذا السؤال .. مهمتك برمجة جزء من برناج رسم ثنائي الأبعاد .. لنقل smart paint .. يمكنك من خلال البرنامج ان تضع اشكال مثلا مربع دائرة خط نقطة .. الخ .. ووظيفتك أن تصمم الكود المسؤول عن اختيار الأشكال أي الكود داخل mouse click event .. مهمتك كتابة كود للتابع التالي: Shape Select(int x, int y) { }; للتسهيل ، يمكنك ان تعتبر أي شكل محاط بمستطيل وبالتالي تسهل عملية فحص إذا كانت الكليك تابعة للشكل ام لا.. أي أن كل shape يحتوي على التالي: class Shape { public int x1, y1, x2, y2; // boundry public bool IsInside(int x, int y); } المطلوب منك تصميم ال data structure لحفظ ال shapes ، أي كيف سوف تحفظ الأشكال بالذاكرة وكتابة الكود الذي يحقق أسرع وقت من أجل ملاقاة الشكل .. :wacko:
  8. سي# 4 ومستقبلها..

    أنصح الجميع برؤية محاضرة Anders Hejlsberg عن السي# 4 ومستقبلها بعد ذلك .. هنا .. الأمور الجديد في سي# 4: 1- dynamic programming: بالمختصر الآن يمكنك تعريف التوابع والمتحولات على أنهم dynamic ويتم تحديد أنواعها أثناء عمل البرنامج .. يمكنك تشبيها ب VBA programming.. أو بشكل آخر يمكنك من كتابة برنامجك باستخدام untyped typed or late time binding . في الواقع سبب استخدام لغات مثل سي# او جافا وتفضيلها عن لغات السكريبت وغيرها هي أنها strongly typed وبالتالي تقلل من الأخطاء البرمجية وتأدي إلى أداء أفضل في بعض الأحيان .. والهدف الأساسي من جعل السي# تعدعم البرمجة الدينميكية لكي تدعم بشكل طبيعي لغات ال untyped مثل python و script languages ، وأخيرا الCOM .. 2- optional and named parameters: وكلنا يعرف ماهي وممتن من أن السي# أخيرا تدعم هذا :) 3- improved COM interoperability: من أجل 1 و 2 .. يمكنك الآن استخدام COM بكل سهولة بنفس الطريقة التي يتم منادتها من VBA .. 4- CO- AND CONTRA-VARIANCE : يمكنك من خلالها مثلا من تمرير مصفوفة من نوع string إلى تابع يقبل مصفوفة من نوع object .. اما مستقبل السي# فتفضل أندريس بعرض سي# compiler as a service .. حيث الآن يمكنك من استدعاء المترجم من برنامجك من أجل ترجمة أي شي وعرض مثال رائع على امكانية كتابة كود سي # من الcommand window .. وتكلم أندريس أيضا عن ال Expressions في الLinq و كيف تم الاستفادة منها في سي# 3 .. إذا أحببت أن ترى مثال عليها فلدي مثال سهل لها في مدونتي هنا
  9. سلسلة شغل مخك - العودة - 1

    دحدوح :) .. حلك كمان قريب .. بس في مشكلة أنا فرضا احب أضح آلاف الأشكال في قسم من الشاشاة .. وفرضا أيضا ممكن أعمل زوم على قسم معين وأرسم فيه كأنه الشاشة كلها .. هل ممكن أن يكون تقسيمك للشاشة ديناميكي مثل binary search ... أعتقد إذا لقيتو طريقة تدمجو طريقة بين حل دحدوح وحل وجدي يكون أفضل :)
  10. سلسلة شغل مخك - العودة - 1

    عجبني متل ما بقولو تفكيرك خارج الصندوق :) فكرتك قريبة من الحل بس فيها مشكلة .. الاحداثيات 10,100 غير 100,10 وبالتالي وضعها في الشجرة لا يكون بشكل صحيح .. المفروض يمكنك استخدام احداثيات x و y على حدا في الشجرة من غير الجمع .. كيف يمكن هذا؟ الأسهل فكر كيف يمكن ان تستخدم x فقط ومن بعدها كيف تستفيد من y ..
  11. سلسلة شغل مخك - العودة - 1

    شكرا أخ دحدوح على الكود وعلى توضيح الكود ل IsInShape .. طريقتك هي نفسها طريقة فهد في الكود المطلوب كتابته وهو Select .. ولكن هل يوجد طريقة أسرع .. الخوارزميات التي كتبتوها هي O(N) .. يجب أن يكون هناك افضل من هذا .. مساعدة : فكرو بتوزع الأشكال على لوحة الرسم ومواضعها وكيف يمكن تصميم data structure مناسب لها :)
  12. انشاء Label داخل New Threard

    هل قصدك ب windows forms? .. لا يفضل استخدام ال controls من ثريد مختلف عن الثريد الأساسي .. لأن الcontrols ليست مبرمجة لتكون آمنة للوصول من عدة threads .. يمكنك استدعاء تابع ليعمل في الثريد الأساسي باستخدام Control.Invoke . هذا التابع يمكنه ان ينشأ أو يعدل في الوندوز فورم.
  13. السؤال الأساسي لم يحدد هذا :)
  14. سلسلة شغل مخك - العودة - 1

    شكرا للمشاركة أخ فهد .. فقط للتوضيح في حلك ال vector يكون في الخارج ويتم اضافه له عند وضع الshapes على لوحة الرسم .. حلك صحيح ولكن: 1- في حال ليدنا المئات من الshapes هل يوجد حل أسرع؟ 2- ماذا لو يوجد أشكال فوق بعضها ، أيها سوف تعيد؟
  15. سلسلة شغل مخك - العودة - 1

    لا.. فقط معرفة اي shape تم الضغط عليه .. مثال لدينا شكل shape1 احداثياته 10,10,100,100 وشكل shape2 احداثياته 200,200,250,250 والمستخدم نقر على الاحداثيات 50,50 فالكود المطلوب يجب ان يرجع shape1 .. أريد أي حل يحقق المطلوب وكودوز لأسرع خوارزمية :)
  16. ليش التعقيد ياشباب! هذا حل دحدوح من غير استخدام مصفوفات ولا ستاك ولا كيو! using System; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { int max = int.MinInt; int min = int.MaxInt; do { Console.Write("Enter value: "); string input = Console.ReadLine(); int val; if (int.TryParse(input, out n)) { if (val > max) max = val; if (val < min) min = val; } else { Console.WriteLine("Invalid value!"); } } while (input != "-"); Console.WriteLine("Min: {0}, Max: {1}", min, max); } } }
  17. بن عوض .. شكرا للتوضيح ... وإذا سمحت لي أن أوضح أكثر .. لا يعني من وجود دالة جاهزة أن يتم استخدامها .. مثلا أفضل من ال sort في هذا المثال يمكن استخدام linq extensions: int[] a = new[] { 1, 2, 3 }; int max = a.Max(); int min = a.Min(); ولها complexety of O(N) مثل الكود الذي كتبته .. ولكن باستخدام دالتي Max و Min يعني أننا سوف نفحص كل رقم مرتين بدال مرة واحدة كما في الكود السابق..
  18. Windows In The Cloud

    المشكلة الآن ، تجد الكثير من مخدمات الويب يقومون بحل نفس المشكلة وهي كيف يمكن زيادة سرعة الموقع والحفاظ على عمله في أوقات الضغط العالية .. أول من أعطى خدمة الاستضافة في بيئة تشبة الcloud هي Amazon في Ec3 . وتلتها جوجل وميكروسوفت . خدمة ميكروسوفت هي مختلفة بعض الشئ عن البقية فهي بيئة تشغيل جديدة تتيح استضافة برامج و خدمات مهما كانت في بيئة الcloud .. بشكل عام أعتقد أن المبرمجين والشركات سوف يتوجهون للcloud لأنها تتيح لهم بيئة مرنة وقابلة للتضخم وهم بالتالي يستطيعون التفرغ في كتابة البرامج نفسها .الcloud مازالت في أولها ومع ذلك تلاقي استحباب واسع والعديد من المطورين بدأو في كتابة برامج وأمثلة عليها . والعديد من المواقع الحالية في الشبكة ممكن كتابتها لتعمل على الcloud بشكل أسرع وأداء أفضل .. فإذا كانت الفرصة متاحة من أجل أن أحمل موقعي على أكثر من سيرفر فلما لا.. المستقبل ل cloud and parallel computing! في المستقبل أعتقد أنه سوف يكون هناك نوعان من البرامج: برامج على سطح المكتب و برامج في الcloud .. فمهما تطورت الانترنت فالمستخدم مايزال يريد بعض البرامج القوية التي تحتاج جهاز قوي من أجل أن تعمل .. أما البرامج الأخرى كمحرر النصوص وخلافها فممكن أن تعمل في ال cloud وفي الجهاز المنزلي ايضا على حسب رغبة المستخدم.. ميكروسوفت أعلنت أيضا بأنها سوف تنتج مجموعة Office من أجل أن تعمل على ال cloud وهي خطوة جديدة في هذا المجال ..
  19. Or even better use: str.EndsWith("someValue", StringComparison.OrdinalIgnoreCase);
  20. They should be compatible.. rename the file to a zip file and open it up.. if it didn't open, it might be corroupted.. refer to this link: http://msdn.microsoft.com/en-us/library/ms185314.aspx
  21. أساسيات ال Threading مشكلة Race Condition

    Nice article.. Parallel C# is just a new extension for C# and also for C++ to allow programmers in C# to write parallel applications easily.. The most powerfull tool now, yet not programmer friendly, that allows you to program on a wide scale (like super computers) is MPI.. The basics of all parallel libraries is to give you methods for reductions (Parallel.Reduce) and expansions (Parallel.For). If you are using lock, don't lock on the (this), because you never know if the caller locks on your object, which would result in dead locks (two resources holding on the same lock).. If you want to use lock, lock on a private member. private object lockObject = new Object(); lock (lockObject) { }
  22. مساعدة لوسمحتم يا أغلى شباب

    شو يعني توكيدات؟
  23. You don't need to sort if you are interested only in the biggest and smallest numbers. Just do a for loop and check on every item.. int max = int.MinValue; int min = int.MaxValue; for (int val...) { if (val > max) max = val; if (val < min) min = val; }
  24. أحيانا يعجز الأسمبلر الموجود بداخل اللغة عن مواكبة تقدم المعالجات وتجده عاجز عن فهم تعليمات الأسمبلي الجديدة . وبما أن الأسمبلر هو دائما اسرع تطويرا من بيئة البرمجة فأحيانا تحتاج إلى كتابة روتينات بشكل منفصل بالأسمبلي وتربطها مع برامجك في السي++ . سوف اشرح هنا كيفية ربط MASM 6.14 مع بييئة Microsoft Visual C++ 6.0 .. طبعا تم اختياري ل MASM 6.14 وذلك لدعمه إلى جميع تعليمات PIII و 3D-NOW و MMX .. سوف أقوم بكتابة كود بالأسمبلي لجمع أعداد في مصفوفة ويعيد نتيحة الجمع . هذا الروتين هو في ملف منفصل امتداده ASM وعندما تقوم بترجمة مشروعك الفيجوال سي++ سوف يتم استدعاء ML.EXE ليقوم بعملية تجميع ملف ال Assembly وانتاج ملف OBJ . هذا الملف يستخدم في ال Linker تبع الفيجوال سي في ربطه مع بقية ملفات ال OBJ في مشروعك .. العملية بسيطة جدا وشوف تتغلم أيضا كيف تنفذ روتين الأسمبلي خطوة خطوة أي Tracing .. من أجل عمليات ال Debugging .. يجب أن يكون لديك نسخة MASM 6.14 من أجل أن تقوم بتجربة المثال التالي . سوف أبدأ بمشروع Console Application فارغ وأقوم باضافة ملف TXT جديد (فارغ) إلى المشروع وأحفظه باسم add.asm وبالتالي تصبح شجرة المشروع كالتالي : الآن اكتب هذا الكود في ملف الأسمبلي : .586P ; directive for the processor used .model FLAT, C ; We need to use all the memory as one segment, and C style _TEXT SEGMENT ; the code segment should be _TEXT ; Your code goes here ; adda is a public procedure which accepts two pointers ; the first parameter is DWORD (pointer 32-bit) ; the second parameter is WORD (16-bit) adda PROC NEAR PUBLIC, array : DWORD, count : WORD mov esi, array ; move the address of the array to esi xor eax, eax ; clear eax mov cx, count ; load the count in ecx .WHILE cx != 0 ; while (cx != 0) { add eax, [esi] ; eax += [esi]; add esi, 4 ; esi += 4; dec cx ; cx--; .ENDW ; } ret ; return eax; adda ENDP _TEXT ENDS END سوف أقوم بشرح البرنامج على السريع : 586P في البداية هي موجه للأسمبلر من أجل تفعيل تعليمات معالجات بنتيوم 1 .. مع تفعيل تعليمات النمط المحمي . استخدمنا MODEL من نوع FLAT لأن هذا هو النوع الذي عليه برامج الويندوز 32bit واستخدمنا لغة التوافق هي C وهذا ضروري من أجل استخدام البارامترات في تعريف التوابع في الأسمبلي بطريقة آلية. كما ترى الروتين تم تحيدي PUBLIC من أجل أن تراه الملفات الأخرى وتم تحديد البارامترات مباشرة . يمكنك طبعا استخدام العديد من الMACROS في MASM وأنا هنا مستخدم WHILE وهي تولد الكود اللازم من أجلها. طبعا يتم إعادة القيمة الموجودة في EAX إلى البرنامج الذي استدعى . الخطوة الثانية وهي كتابة ال prototype لهذا الروتين في ملف السي الذي يريد استدعائه وهو كالتالي ..: extern "C" int adda(int*, short); كما تلاحظ استخدامنا ل "extern "C وهي ضرورية إذا كنت تترجم في سي++ وذلك بسبب أن السي++ تستخدم أسماء مختلفة للروتينات تعتمد على أنواع البارامترات . يعني داخليا التابع adda في سي++ يتغير إلى شيئ يشبه [email protected]@[email protected] وهذا الاسم يدل على نوع البارامترات . هذا سبب أن السي++ تسمح با overloading للتوابع (حيث نفس اسم التابع يمكن اعادة برمجته مع تغيير انواع البارامترات ) . الآن بما أن الأسمبلي ليسة متوافقة مع هذه التواقيع في سي++ فيجب أن نقول لسي++ أننا لا نريد توليد هذه الأمور ونريد أن يتم معاملة هذا التابع كما لو أنه مبرمج في السي . هذا سبب استخدامنا إلى "extern "C . الخطوة التي يمكن عملها في اي وقت وهي كيفية أن تقول للفيجوال سي++ أننا نريد استخدام ML.EXE من أجل عمل تجميع لملف الأسمبلي لدينا ... هذا سهل عن طريق ما يلي : اضعط بالزر الأيمن على ملف الأسبملي واختر Settings من القائمة . وسوف تظهر لك نافذة Project Settings ومعلم على الملف add.asm واذهب إلى الصفحة Custom Build على اليمين . كما هو موضح في الصورة : إن Custom Build من اسمها تسمح لك بتحديد بطريقة يدوية كيف سوف يتم ترجمة الملف وهنا طبعا سوف نضع الصيغة الصحيحة من أجل استدعاء ml.exe .. طبعا سوف تكتب صيغتين واحدة من أجل ال Release والأخرى من أجل ال Debug . يتم اختيار الRelease و الDebug من Settings For . لماذا هذا الاختلاف بين الRelease و ال Debug .. طبعا أنت تعلم أنه في نسخة ال Debug لمشروعك فإنك تستطيع أن تقوم بتنقيح البرنامج وتنفيذه خطوة حطوة ومشاهدة المتحولات . هذا ناتج لأن الفيجوال سي++ تقوم بتوليد معلومات ال debug في ملف امتداده pdb هذا الملف يحتوي على جميع المعلومات الضرورية من أجل المنقح ليعلم عن المتجولات وعلاقة لفة الآلة بكود السي++ . ومن أجل أن تستطيع أن تقوم بتنقيح ملف الأسمبلي تبعك يجب أن تخير ال ml.exe أنك تريد توليد معلومات ال debug . برنامج ال ml.exe هو عبارة عن Command Line Assembler أي يتم تمررير الخيارات عن طريق بارامترات في الcommand line وقت تنفيذه .. يوجد العديد من البارمترات وممكن أن تحصل عليها عن طريق تنفيذ ml.exe /help .. لنرجع إلى نافذة Project Settings .. من أجل الRelease قم بكتابة ما يلي في صندوق الcommands : // أكتب هذا في مربع commands f:masm614binml.exe /c /Cx /coff /Fo$(ProjDir)Release$(InputName).obj $(InputDir)$(InputName).asm // أكتب هذا في مربع Outputs $(ProjDir)Release$(InputName).obj الماكروات التي تراها في النص السابق يمكن الحصول عليها بسهولة عن طريق الزرين Directory و Files .. سوف أقوم بشرح البارامترات المستخدمة هنا وهي : c : تعني عملية تجميع assemble من غير ربط link .. ينتج منها ملف مصدري obj فقط . Cx : يجب أخد حالة الأحرف الصغير والكبير في التوابع العامة public . coff : تنتج ملف obj متوافق مع بيئة الفيجوال سي++ ، وهي نوع متطور عن النوع القديم obj . Fo : تحدد موقع ملف ال obj الناتج وهنا وضعته في دليل المشروع ومنه في دليل Release . ومن ثم تحدد اسم الملف الذي تريد تجميعه وهو هنا في حالتنا تم تحديده عن طريق الماكروات المتاحة. أما في مربع Outputs فمن خلاله تخير الفيجوال سي++ أين يتوضع الملف الناتج ومنه تستطيع أن تعلم متى أصبح الملف قديم من أجل ترجمته أو تجمبعه من جديد . بالنسبة إلى ال debug فأكتب مايلي : // أكتب هذا في مربع commands f:masm614binml.exe /c /Cx /coff /Zd /Zi /Zm /Fo$(ProjDir)Debug$(InputName).obj $(InputDir)$(InputName).asm // أكتب هذا في مربع Outputs $(ProjDir)Debug$(InputName).obj سوف أشرح هنا فقط البارامترات الاضافية : Zd : تضيف أرقام الأسطر وكود السي الأساسي إلى ملف الobjet Zi : تضيف أسماء المتحولات إلى ملف ال object Zm : معلومات التنقيح متوافقة مع MASM 5.10 .. (وذلك للاحتياط) وطبعا هنا فقط عدلنا من الدليل Release إلى Debug .. الآن عندما تقوم بترجمة مشروعك فإن الفيجوال سي++ سوف تستدعي MASM بشكل آلي من أجل تجميع الملف وسوف تظهر نتيجة التجميع في شاشة الخرج وسوف تظهر جميع الأخطاء في شاشة الخرج output كما في الصورة التالية .. حيث قمت بافتعال كم خطأ في كود الأسمبلي : ولاحظ عند الضغط على أي خطأ مرتين يتم الذهاب مباشرة إلى السطر الخطأ .. الآن من أجل تجربة البرنامج والتأكد من عمله أكتب مايلي في ال main : extern "C" int adda(int*, short); int main() { int arr[] = { 1, 2, 3 }; int sum; sum = adda(arr, sizeof(arr)/sizeof(int)); printf("sun = %dn", sum); return 0; } وتأكد أنك مختار Debug في Set Active Configuration في القائمة Build .. وذلك لأننا نريد تنفيذ البرنامج خطوة خطوة .. والآن قم بترجمة المشروع عن طريق الضغط على F7 ومن ثم بعد أن تتأكد من عدم وجود أخطاء قم بتنفيذ البرنامج خطوة خطوة عن طريق الضغط على F11 .. واستمر بالتنفيذ .. وإذا كانت جميع خطواتك مثل ماذكرت سابقا فيجب أن تستطيع الدخول إلى ملف الأسمبلي وتنفيذه خطوة خطوة .. ويمكنك أن تفعل نافذة مشاهدة المسجلات أو تضع watch للمتحولات المستخدمة في البرنامج تماما مثل ماتفعل في السي++ . وهذه الشاشة توضح ذلك : لاحظ أن يوجد عرض لمسجلات ال MMX من MM0 إلى MM7 كل واحدة بعرض 64بت ومسجلات الجديدة في PIII وهي XMM0 إلى XMM7 وكل واحدة بعرض 128 بت .. وطبعا المسجلات العادية .. وعند تنفيذ الكود سوف تحصل على النتيجة الصحيحة .. هناك عدة أمور يجب الانتباه عليها وهي تسمية المقاطع .. فرضا إذا أردت أن تضع DATA في برنامج الأسمبلي فيجب أن تكون في مقطع _DATA أو _BSS أو CONST .. والكود كما لاحظت في _TEXT وذلك حتى يعرف الlinker كيف يقوم بعملية الربط .. في النهاية .. أقول أنه طبعا يمكنك استخدام ال inline assembly في الفيجوال سي++ مباشرة عن طريق استخدام الكلمة المحجوزة __asm .. وإن لم تكن تعلم فهي تدعم إلى معالج ال MMX . وهي عملية جدا .. ولكنها غير كفئ من أجل المحترفين والذين يريدون التحكم في روتين الأسمبلي بشكل كامل و ايضا هذه الطريقة عملية من أجل كتابة أو نقل الروتينات التي كتبت بشكل منفصل في ملفات أسمبلي منفصلة بحيث يتم دمجها مع مشروعك بطريقة عملية .. المشروع موجود في الوصلة : http://arabteam.nicmatic.com/atassi/masm2vc4.zip
  25. طلب بسيط عن vTable

    ال vTable من أهم الأمور في الوراثة في السي++ . وهي عبارة بكل بساطة عن مصفوفة في الذاكرة كل عنصر فيها يعتبر عن مؤشر لتابع داخل الكلاس . مؤشر هذه المصفوفة موجود في أول ال Object لهذا الكلاس في الذاكرة . عندما تقوم بكتابة كلاس يحتوي على هدة توابع . فرضا اعتبر الكلاس التالي : class base { public: void func1() { printf("I am base::func1n"); } void func2() { printf("I am base::func2n"); } void func3() { printf("I am base::func3n"); } }; base obj; طبعا أنت تقر أن التابع func1 و func2 موجودين في الذاكرة بازاحات معينة ولتكن 400 و 500 على الترتيب . الآن عندما تكتب مثلا : obj.func1(); فإن المترجم يفهم مباشرة العبارة السابقة على أنها استدعاء للتابع func1 من base ويقوم باستدعاء العنوان 400 . وسوف يطبع النتيجة : I am base::func1 الآن إذا قمنا بوراثة الكلاس son من base بحيث يعيد الكلاس son تعريف التوابع func1 و func2 أما func3 فورثناه بدون تغيير : class son : public base { public : void func1() { printf("I am son::func1n"); } void func2() { printf("I am son::func2n"); } }; son obj; base *ptr = &obj; // this is valid because base is a father of son لاحظ كيف أصبح لدينا كائن في الذاكرة من نوع son ومن ثم حجزنا متحول من نوع مؤشر إلى base وأعيطناه عنوان ال son . الآن إذا قمنا باستدعاء التابع func1 عن طريق obj فإننا نحصل على النتيجة : I am son::func1 ومن ثم من ptr فإننا نحصل على النتيجة : I am base::func1 النتيجة الاولى منطقية أما الثانية فلماذا نفذ التابع الخاطئ مع أنه لدينا كائن من son وليس base .. في الحقيقة قام المترجم بفهم العبارة Ptr->func1() على أنها استدعاء للتابع func1 الذي داخل الكلاس base وقام بتكوين لغة الآلة التي تقوم باستدعاء الموقع 400 مباشرة . في الحقيقة بما ان التابع func1 لا يصل إلى أي متحولات داخل الكلاس base فإنك حتى لو وضعت قيمة المؤشر ptr تساوي NULL فإن الكود يعمل بنجاح . من أجل حل المشكلة السابقة نلجأ إلى ال vtable .. فكما لاحظت في الأمثلة السابق فإن عملية تحديد أيها تابع يجب أن يستدعى هي مسؤلية المترجم أي ال compiler وهذا يسمى ب early binding . أما في ال vtable كما سوف ترى فإن المترجم ليس له علاقة ويتم تحديد التابع الذي سوف يستدعى أثناء التنفيذ وهذه تسمى late binding .. يتم بناء ال vtable لأي كلاس إذا تم اعطاء أي تابع ضمني داخل الكلاس الخاصية virtual . أي يكفي تابع واحد فقط من أجل بناء مصفوفة ال vtable . لو فرضنا أننا قمنا بتغيير الكلاسين السابقين بحيث يصبحا يحتويان على مصفوفة ال vtable .. كالتالي : class base { public: virtual void func1() { printf("I am base::func1n"); } virtual void func2() { printf("I am base::func2n"); } virtual void func3() { printf("I am base::func3n"); } }; class son : public base { public : virtual void func1() { printf("I am son::func1n"); } virtual void func2() { printf("I am son::func2n"); } }; base obj_base; son obj_son; الآن ماذا أصبح لدينا : لو قمت بفحص المتحول obj في بيئة ال Visual C++ أثناء ال Debug فإنك سوف تحصل على التالي : لاحظ أن أول حجرة في الكائن obj_base في الذاكرة هي عبارة عن متحول ضمني من نوع مؤشر إلى مصفوفة هذه المصفوفة تحتوي على ثلاثة عناصر بعدد توابع الvirtual في الكلاس . وأيضا لاحظ إلى ماذا يؤشر كل عنصر في المصفوفة . ولاحظ الكائن obj_son الذي يحتوي أيضا على ثلاث عناصر لكنه يشارك نفس الكود تبع func3 مع الكلاس base . ويمكن توضح الرسمة التالية أكثر : يجب أن تنتبه إلى أمر وهو أن ترتيب وجود المؤشرات في ال vtable هو نفس ترتيب وجودها في ال class أي الذي يأتي أولا يتوضع أولا وهكذا . الآن إذا قمنا بكتابة الكود التالي: base *father = &obj_son; father->func2(); بما أن التابع func2 هو عبارة عن virtual فالمترجم لن يعرف أثناء الترجمة ألى أين يسند الاستدعاء ويقوم بتوليد الكود المناسب الذي يستخلص عنوان التابع من ال vtable . obj_son يحتوي على ال vtable التي رأيتها سابقا وعندما نقوم بأخذ عنوان هذا الكائن واسناده إلى متحول father الذي من نوع مؤشر إلى base فإن father في هذه الحالة يؤشر إلى vtable تبعة obj_son وبالتالي التابع func2 في هذه الحالة سوف ينفذ بطريقة صحيحة ويظهر النتيجة : I am son::func2 بالنسبة لل COM فإنه أساس تعامل الCOM هو ال vtable .. إن كائنات الCOM تحتوي على Interfaces كل Interface هو عبارة عن Classe هذا الكلاس يحتوي على العديد من التوابع أو Methods . وعند استخدام هذا الCOM في أحد برامج ال client فإنها تحصل على أحد ال Interfaces التي تريد التعامل معها ومن هذه الواجهة تبدأ باستدعاء التوابع . ولكن كيف تعرف ال client أين موجود التابع من أجل استدعائه .. يتم هذا بأن تحتوي ال Interface أو الClass عند بنائه في الذاكرة على vtable . وال Client فقط تعرف ال prototype تبعة التوابع وأماكن وجودها أو ترتيبها في ال Class وبالتالي تعرف أين سوف تأخذ قيمة مؤشر التابع من ال vtable .. طبعا بعض ال clients لا تدعم ال vtable مثل ال vbscript و jscript و ال asp و و و. ففي هذه الحالة يستخدم IDispatch من أجل تنفيذ التوابع . بالنسبة إلى afx_msg فليس لها أي علاقة .. وهي لا شيئ .. أي تستبدل بلا شئ .. انظر تعريفها في الملف afxwin.h . الآن بالنسبة إلى AFX_NOVTABLE فهي معرفة على أنها __declspec(novtable) إلى __declspec مستخدمة من أجل توسع للغة أو بيئة معينة ف Microsoft لها العديد من الأضافات على لغة السي++ أحدها novtable . وهي تستخدم بعد الأمر class من أجل عدم تكوين vtable للobject .. وهذا لا يعني أن طريقة التعامل هنا أصبحت early binding لا بل بقيت late binding ولكن لا يتم توليد vtable فقط . وهذا مفيد في حالة لدينا class في سلسلة الوراثة لا نستخدمه مباشرة وبالتالي لا يتم استخدام ال vtable خاصته وهذا يعني توفير في الذاكرة في حالة تم الغاء تكوين ال vtable لذاك الكلاس . لشرح ذلك قم بوراثة كلاس آخر من البرنامج السابق ليصبح البرنامج كالتالي : class base { public: virtual void func1() { printf("I am base::func1n"); } virtual void func2() { printf("I am base::func2n"); } void func3() { printf("I am base::func3n"); } }; class __declspec(novtable) son : public base { public : virtual void func1() { printf("I am son::func1n"); } virtual void func2() { printf("I am son::func2n"); } }; class grandson : public son { public : virtual void func1() { printf("I am grandson::func1n"); } virtual void func2() { printf("I am grandson::func2n"); } }; base obj_base; son obj_son; grandson obj_grandson; int main(int argc, char* argv[]) { base *ptr; ptr = &obj_son; ptr->func1(); ptr = &obj_grandson; ptr->func1(); return 0; } لاحظ كيفية وضع __declspec(novtable) بعد كلمة class .. وهذا يعني عدم تكوين مصفوفة ال vtable .. قم بوضع break point في بداية البرنامج وادرس ال watch : لاحظ أن المترجم عامل الكلاس son على أنه لديه vtable ولكن لاحظ مؤشر ال vtable يؤشر إلى vtable الأب وبالتالي لا يوجد مصفوفة جديدة تم حجزها خصوصي من أجل الكلاس son أما الكلاس الجديد فله vtable مثل العادة . في هذه الحالة يجب أن لا نستخدم الكلاس son أبدا لأنه قد يؤدي إلى مشاكل مثل المثال السابق في ال main .. عندما تكتب أي COM باستخدام ال ATL فإنك سوف تجد أن الويزارد قام بوضع AFX_NOVTABLE عند الكلاس الذي تكتب فيه كود ال Interface لأنه في الحقيقة لانحتاج إلى vtable هنا وذلك بسبب أنك مطلقا وأبدا سوف تستخدم هذا الكلاس كobject وذلك بسبب أن ال ATL تسخدم كلاس آخر اسمه CComObject يرث من الكلاس تبعك والكلاس الناتج يتم منه بناء object بالذاكرة وبتم ارساله إلى ال client وهذا كله يتم في IClassFactory ... ومكنك الرجوع إلى كود ال Factory في ال ATL ... هذا مالدي .. إذا عندك أي أسئلة فأنا جاهز ..