• 0
ahmed.o.mohamed

برأيك, ما هي قيمة n !؟

سؤال

السلام عليكم و رحمة الله و بركاته

كلنا يعرف أهمية الـ bitwize في حياتنا البرمجية, لذلك قمت بطرح هذا السؤال البسيط جدا, لكي يتمرن القارئ على التعامل مع هذه المخلوقات العجيبة .. أقصد الـ bitwize

إليك المثال :

int n=0;int m=1<<8;int x=8+2;while(m){n+=x&m;m=m>>1;}

تُرى, ما هي قيمة n في نهاية الكود ؟, برر إجابتك :wink:

بالتوفيق.

تم تعديل بواسطه مصطفى 36a2
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

19 إجابة على هذا السؤال .

  • 0

الاجابه هي 10

التفسير:

قيمة n في بداية الكود هي 0

السطر قبل اللوب


int m=1<<8;

يقوم بعمل شيفت لm ثمانية خانات يعني m = 2^8

الان داخل الكود

السطر


n+=x&m;

يقوم بعمل AND بين x و m هذه العملية سوف ترجع صفر الا في حالتين التي هي عندما m = 2^3 وعندما m= 2^1 و هذه العملية تعرف بعملية masking

السطر


m=m>>1;

يقوم بعمل شيفت عكس لقيمة mبمقدار خانة واحده يعني في اول لوب m يصبح 2^7 ثم 2^6 وهكذا

طبعا اللوب ينتهي عندما نعمل شيفت لm و m تساوي 1 حيث تصبح قيمة m 0 ونخرج من اللوب

اذا قيمة n تساوي


n = 0(2^8) + 0(2^7) + ..... +1(2^3) + 0(2^2)+1(2^1)

اتمنى ان تكون هذه الاجابة مقنعة

تم تعديل بواسطه mental-driller
1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0


int m=1<<8;

العملية المطبّقة تسمى Shift left وهي تماثل الضرب بـ 2x حيث أن x هي القيمة في أقصى اليمين (8) وبالتالي قيمة m هي 1*28 = 256 (القيمة الابتدائية)


n+=x&m;

العملية المطبّقة هي AND ومعروف أن 1&1=1 وكل ما عدا ذلك 0 (هنا الـ 1 والـ 0 تمثل البتات وليس العدد الصحيح واحد)


m=m>>1;

هذه العملية معاكسة للسابقة وتسمى Shift right وتمثل القسمة على 2x حيث x هنا هي القيمة 1

بالتالي فقيمة m تساوي (2/m)

من هذا نجد بأنه في كل دورة للحلقة تنقص قيمة m بمقدار النصف.

ونجد بأن n تأخذ قيمتها من المعادلة


n = n + x&m;

لكن قيمة x دوماً 10 (تقابل 1010 في التمثيل الثنائي)

وبما أن قيمة m تتناقص بمقدار النصف فيمكننا التوقع بأن m عندما تصبح 8 (تقابل 1000 بالتمثيل الثنائي) وعندما تصبح 2 (تقابل 10 بالتمثيل الثنائي)، سيكون ناتج تنفيذ العملية & بين x و m يساوي لقيمة m (لأن 1&1=1 وفيما عدا ذلك 0 كما ذكرت سابقاً).

هذا يعني أن قيمة n ستكون 2+8=10

وتنتهي الحلقة عندما تصبح قيمة m مساوية لـ 0 بعد أن تصل إلى 1/2 (لكنها عدد صحيح لذلك سيهمل الجزء الكسري).

1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0


n=0 // 0000 0000
m=16 // 0001 0000
x=10 // 0000 1010


m -> 16
n += x & m = 10 & 16 = 0 // n = 0
m >>= 1 // m = 8 // 0000 1000

m -> 8
n += x & m = 10 & 8 = 8 // n = 8
m >>= 1 // m = 4 // 0000 0100

m -> 4
n += x & m = 10 & 4 = 0 // n = 8
m >>= 1 // m = 2 // 0000 0010

m -> 2
n += x & m = 10 & 2 = 2 // n = 10
m >>= 1 // m = 1 // 0000 0001

m -> 1
n += x & m = 10 & 1 = 0 // n = 10
m >>= 1 // m = 0 // 0000 0000

result n = 10, m = 0, x = 10

و الله ولي التوفيق

2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

كل الطرق تؤدي إلى البصرة !..!, أقصد روما :lol:

اتمنى ان تكون هذه الاجابة مقنعة

إجابة جميلة و شرح واضح أيضا :cool:

هذا يعني أن قيمة n ستكون 2+8=10

إجابة رائعة .. بنكهة أسمبلاوية :wub:

result n = 10, m = 0, x = 10

بالضبط :clapping:

الخلاصة : فكرة مؤثرات الإزاحة تدور حول الملأ و المسح : لكي تفهم مؤثرات الإزاحة بشكل أفضل يمكنك اعتبار أن إزاحة عدد معين 5 خانات لليمين تكون باستبدال الخمس خانات الواقعة يسار العدد بأصفار أما الإزاحة لليسار فتكون باستبدال الخمس خانات الواقعة يمين العدد بأصفار, وهكذا ...

اقتراح :

ما رأيكم أن يكون هذا الموضوع متخصص في إيضاح الأشياء التي عادة ما يصعب فهمها على المبتدئين,المتوسطين أو حتى المحترفين :wink: و بهذا يكون هذا الموضوع جامعا للكثير من الكنوز التي يمكن أن تتناثر في مواضيع مختلفة .. مما يُشتت ذهن الزائر و يقلل من الإستفادة !

أقترح أن يضع العضو (أول مجيب على السؤال المطروح) فائدة جديدة و يضع خلاصة القول بعد انتهاء النقاش لتكون تلك الخلاصة ختام مسك للقضية السابق نقاشها و هكذا دواليك ...

بانتظار مختلف الآراء ... خصوصا من الإدارة :rolleyes:

تم تعديل بواسطه أحمد المتألق
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

احد فوائد البيت وايز القديمة bitwise ايام ماكان المعالج مافيه ريجسترات كثيرة

فكانت العملية


int temp = x;
x = y;
y = temp;

مكلفه جدا لذا كان يستخدم الxor لتبديل البيانات بين متغيرين بدون استخدام temp variable

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0
لذا كان يستخدم الxor لتبديل البيانات بين متغيرين بدون استخدام temp variable

يعم ربنا يخلي xchg بـ 3 سطور و 4 clocks العمليه تمت بأسرع ما يمكن و بنجاح تام و لا احلي من كده، خد عندك المثال ده:


int a = 10, b = 20;

__asm
{
mov eax, a ; 1 clock
xchg eax, b ; 2 clocks
mov a, eax ; 1 clock
}

و الله ولي التوفيق

تم تعديل بواسطه محمد علاء الدين
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

يعم ربنا يخلي xchg بـ 3 سطور و 4 clocks العمليه تمت بأسرع ما يمكن و بنجاح تام و لا احلي من كده، خد عندك المثال ده:


int a = 10, b = 20;

__asm
{
mov eax, a ; 1 clock
xchg eax, b ; 2 clocks
mov a, eax ; 1 clock
}

و الله ولي التوفيق

بالتاكيد اذا كانت اللغة تدعم inlining مع اسمبلي ،

بالنسبة للامر xchg اعتقد انه يقوم بنفس العملية اللي هي الxoring بس على مستوى الcontrol unit

بالمناسبة لا اعقتد ان الامر ياخذ اربعه clocks

اعتقد ان ال RTL الخاص بامر MOV لحالة بياخذ تقريبا خمس clock cycles

تم تعديل بواسطه mental-driller
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0
بالتاكيد اذا كانت اللغة تدعم inlining مع اسمبلي ،

و لو كانت لا تدعم فيمكن استخدام الـ shell code، مثلا الدوت نت لا تدعم الأسمبلي على الإطلاق لذا يتم تحويل الكود بالأعلي للـ machine code مع إبدال أسماء المتغيرات بموقعها داخل الـ stack و بعدها وضع داخل الذاكره و انشاء delegate يشير للكود الذى تم وضعه بالذاكره و بصمت الـ delegate تحتوى على متغيرين من نوع int - على سبيل المثال.

الكود التالي كنت كتبته للحصول على عنوان PEB و TEB الخاص بالـ process الحالي (الكود بالـ vb):


Imports System.Runtime.InteropServices

Public Class NativeWin32

Private Delegate Function NativeFunction() As IntPtr

Private Shared codePEB As IntPtr
Private Shared codeTEB As IntPtr

Private Shared dPEB As NativeFunction
Private Shared dTEB As NativeFunction

Shared Sub New()
codePEB = Marshal.AllocHGlobal(14)
codeTEB = New IntPtr(codePEB.ToInt32 + 7)

' getPEB
' mov eax, fs:[30h] ' 64:A1 30000000
' ret ' C3

'***************************************

' getTEB
' mov eax, fs:[18h] ' 64:A1 18000000
' ret ' C3

Marshal.Copy(New Byte() {&H64, &HA1, &H30, &H0, &H0, &H0, &HC3}, 0, codePEB, 7)
Marshal.Copy(New Byte() {&H64, &HA1, &H18, &H0, &H0, &H0, &HC3}, 0, codeTEB, 7)

dPEB = Marshal.GetDelegateForFunctionPointer(codePEB, GetType(NativeFunction))
dTEB = Marshal.GetDelegateForFunctionPointer(codeTEB, GetType(NativeFunction))
End Sub

Public Shared Function GetCurrentPEB() As IntPtr
Return dPEB()
End Function

Public Shared Function GetCurrentTEB() As IntPtr
Return dTEB()
End Function

End Class

**************************

على فكره فى المشاركه بتاعتى رقم 4 قيمة m خطأ لأنى افتكرت ان الـ 8 سيتم إجراء shift left لها بمقدار 1 و الصحيح أن 1 سيتم إجراء shift left لها بمقدار 8 و حيث ان داخل الـ loop قيمة x لا تتغير و ايضا تصادف ان 8 هى من مضاعفات الرقم 2 و مع وجود عملية AND أصبح الرقم 16 هو تبسيط للعمليه حيث الرقم 256 بعد عدة LSHIFT سيصبح 16 و عندما يصل لذلك الرقم ستكون قيمة n لأ تزال صفر.

**************************

التعليمه xchg تأخذ 3 clocks و ليس 2، اما mov فتأخذ 1 clock، هذا الكلام استنادا للقيم الموجوده بموقع faydoc.tripod.com، بالطبع هذه القيم تفترض عدة امور منها ان الـ page التى تحتوى على القيم التى سيتم تبادلها موجوده بالذاكره.

التعليمه MOV يختلف عدد الـ clocks بنوع المعاملات فالتعامل مع المسجلات العامه و الذاكره قيمته 1 clock داخل protected mode اما داخل الـ real mode أو ععند التعامل مع المسجلات الأخرى - Debug, Control - فعدد الـ clocks سيزيد بكل تأكيد.

و الله ولي التوفيق

تم تعديل بواسطه محمد علاء الدين
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

الinstruction cycle لا اعقتد انها تتم في clock واحد

وذلك لان الfetch cycle

بنحتاج على الاقل نحمل الaddress register بالعنوان المطلوب PC

ثم نضع الناتج في الdata register

ثم نستخلص من الdata register الامر ونضعة في ال instruction register الذي سوف ينفذ الامر في الexecution cycle

وفي دورة تنفيذ الامر يمكننا اما وضع البيانات من عنوان الذاكرة [M[AR في Accumulator ومنه الى السجل او نضعة في السجل مباشرة

هنا دورة التنفيذ ممكن تكون عبارة عن clock واحدة بس الامر ككل لا ارى كيف ياخذ one clock cycle الا اذا كانت انتيل تستخدم تقنية غابت عني

بس من المنطقي القول اننا نحتاج على الاقل ثلاث نبضات زائد نبضة واحده للتنيفذ

لاحظ اني اغفلت مسألة الInterpertion cycle

للتبسيط

مصادري : Computer System Architecture : Morris Mano

Computer Organization and Architecture: Designing for Performance : William Stallings

Logic and Computer Design Fundamentals: Morris Mano

لاحظ ايضا انه لايمكن لنا ان نفترض ان جميع العمليات هذه قد تتم في لحظة واحدة لانه لايمكن ان نضغط طرف التحميل الخاص بالسجل وفي نفس الوقت نرسل البيانات الى سجل اخر

تم تعديل بواسطه mental-driller
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

عدد الـ cycles التى ذكرتها و التى ايضا موجوده بالموقع المذكور فى المشاركه 9 هو execution time الذى تأخذه هذه الـ instruction للتنفيذ فقط و لم يأت على ذكر الـ Interpertion cycle لأن الأمر هنا مختلف حيث لغة الأسمبلى التى تكتبها ليست هى التى يتعامل معها المعالج و ذلك لأن كل معالجات إنتل توجد بها طبقه وسيطه يتم تمرير لها الـ machine code و تنتج fixed size code stream و هى مختلفه عن التى نتعامل معها، أى يمكنك قول أن معالجات إنتل هى فعليا معالجات RISC مع وجود طبقه عليا لتحويل الـ code stream من CISC إلى RISC.

أبضا لا تنسي أن المعالج يقوم بعمل fetch للـ instruction stream داخل الـ cache - بمساحه محدده - و ذلك لتقليل الدخول على الذاكره و هذا يجعل عملية الـ Interpertion هى عملية تحويل الكود من CISC إلى RISC داخل الـ layer الموجوده بالبروسسور، عملية التحويل هذه لا تأخذ أكثر من 2 cycles داخل كاش البروسسور.

لذا عملية الـ fetch للـ instruction stream لن نقوم بحسابها لأنها تتم بفتره قبل الوصول لمكان التنفيذ و كذلك الـ decode من CISC إلى RISC يأخذ 2 cycles فقط لذا كل ما يتبقى هو عملية fetch البيانات من memory داخل الـ cache و ستكون سريعه إذا كان العنوان aligned أيضا عملية fetch البيانات من الذاكره تتم على blocks لذا قد يكون مساحة الذاكره التى نريد إجراء swap عليها موجوده بالفعل داخل الـ cache و بالتالي لن نأخذ أى وقت للتبديل حيث الكود تم تحويله و البيانات داخل الـ cache لذا كل ما سنحتاج هو وقت الـ swap.

الـ layer الموجوده بالبروسسور لتحويل الـ variable-length instruction stream إلى fixed-length instruction stream إسمها micro-op و هى internal للبروسسور فقط و لم يتم إعلان صيغتها.

المعلومات السابقه - كلها و بالأخص المتعلقه بـ micro-op - موجوده بكتاب x86 Instruction Set Architecture الإصدار الأول بالفصل الأول تحت البند IA Instructions vs. Micro-ops و هى:

Complexity vs. Speed Dictated a Break With the Past:

Nonetheless, in order to continue its relentless march towards ever faster processor

speeds, Intel had to take action. The break with the past occurred with

the advent of the Pentium Pro in 1995, a processor that employed an on-die

instruction set translator. The variable-length x86 instructions were fetched

from memory into the processor’s cache. In strict program order, the complex

x86 instructions comprising the program stream were then fed to an array of

decoders that translated each x86 instruction into a set of one or more simple,

fixed-length instructions (referred to as micro-ops) which, when executed, would

accomplish the same function. In other words, the Pentium Pro and all subsequent

Intel processors are, in fact, RISC machines.

Why Not Publish a Micro-Op ISA?

That raises an interesting question: why didn’t Intel publish an ISA specification

for the new instruction set and make compilers available to produce

machine language object code that could be processed directly by the new breed

of processors? It would be a simple matter to inform a processor that the code it

is fetching from memory is comprised of x86 or micro-op object code and, in the

case of the latter, the code translator logic (the instruction decoders) would then

be bypassed.

The answer is simple. If Intel had, in fact, done this, they would then be obligated

to support yet another instruction set going forward into the future. Furthermore,

having made this new instruction set visible to the outside world,

they would not have the freedom to switch to another, perhaps more efficient

form of internal instruction set in future products.

الصوره التاليه من مقال Intel's Atom Architecture: The Journey Begins بتاريخ 4/2/2008

macroop.jpg

خلاصة القول:

1- معالجات إنتل هى معالجات RISC مع وجود طبقة لتحويل كود CISC إلى RISC و ذلك للإبقاء على الـ backward compatibility و ايضا للإبقاء على وجود إنتل.

2- عملية التحويل من CISC إلى RISC لا تأخذ أى cycles - اتكلم هنا عن الـ clock التى يتعامل معها المستخدم و ليس الداخليه.

3- وجود الـ cache يسرع كثيرا من عمليات التنفيذ حيث فى الأغلب المناطق التى يحتاجها تكون موجوده داخل الـ cache.

4- الوقت المستغرق فى التنفيذ يكون بسبب العمليات التى تقوم بها التعليمه او لأن المعالج يحتاج لإجراء عمليات إضافيه لإخراج البيانات من مكان not-aligned.

المراجع المستخدمه:

x86 Instruction Set Architecture

The Art of Assembly DOS Edition

Intel 64 and IA-32 Architectures Optimization Reference Manual

The Shell Coders Handbook 2nd Edition

بعض المقالات على الإنترنت

** معذره لصاحب الموضوع على تغييري لمسار النقاش **

و الله ولي التوفيق

تم تعديل بواسطه محمد علاء الدين
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

معلش يا محمد بس استحملني شويه

مافيش في الكلام المذكور من كتاب انتيل مايدل على عدد النبضات الذي ياخذه الامر ، انا اضل متمسك برأيي انه لايمكن تحت اي ضرف من الضروف ان نحصل على امر ينفذ في نبضة ايقاع واحدة

ماذكرته عن استخدام الكاشي للتسريع ، بغض النظر عما اذا كان المعالج يتعامل مع M1 او M2 او مع Register file لتسريع عملية الولوج، فانا اقصد بالذاكرة الذاكرة التي يتعامل معها المعالج بشكل مباشر سوءا كانت الرم او الكاشي ، وذلك بترك تفاصيل سرعة الولوج الى الذاكرة وثمن هذا الولوج مهملة

ايضا يجب ان اتفق مع المذكور في الاعلى فيما يخص اختلاف زمن التشغيل لكل امر، وهو ما يجعل تصميم المعالج معقد اكثر ، لانه لو كانت كل الاوامر لها نفس عدد الايقاعات الذي سوف يكون max(instruction length) وذلك بعمل حشو لNOP نبضات فارغة لمساواة زمن الايقاع لكان تصميم المعالج اسهل ولكن اقل فعالية

اعتقد ان هذا هو سبب تصنيف سرعة المعالجات حسب الMIPS وليس حسب سرعة النبضات بالميغاهيرتز او عدد النبضات في كل امر

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0
مافيش في الكلام المذكور من كتاب انتيل مايدل على عدد النبضات الذي ياخذه الامر

كلامك صحيح و لكن توجد فقره تحدد كيب تقوم بحسابها، فى كتاب Volume 3B: System Programming Guide, Part 2 الفصل 30 بعنوان Performance Monitoring الفقره رقم 10 بعنوان Counting Clocks تشرح لك بالتفصيل كيف تحسب عدد الـ clocks لأى تعليمه - أو تعليمات (زمن تنفيذ جزء معين من الكود) - و ايضا تحدد لك كيف تحصل عليها بدقه كبيره و ذلك بتلاشى النقاط التى قد تسبب إرجاع قيم غير صحيحه و كتطبيق على هذه النقطه داخل كتاب CPUID instruction اخر جزء منه الخاص بمثال حساب سرعة البروسسور عن طريق إستخدام RTSC و هي احد الطرق التى يتم شرحها فى الفقره رقم 10 المذكوره بالأعلي.

أيضا يحدد كتاب Volume 3B: System Programming Guide, Part 1 الفصل 16 بعنوان Debugging, Profiling Branches and Time- Stamp Counter الفقره 16 بعنوان Time-Stamp Counter يقال بها ان قيمة الـ Time-Stamp Counter تختلف بإختلاف المعالج فبأحدهم يتم تحديثها تبعا لـ normal clock و بأخر تبعا للـ internal clock.

انا اضل متمسك برأيي انه لايمكن تحت اي ضرف من الضروف ان نحصل على امر ينفذ في نبضة ايقاع واحدة

عندما تقوم بكتابة تعليمات غير مرتبطه ببعضها حينها يقوم المعالج بتنفيذهم بشكل متوازى - فيما يظهر لنا أو تبعا للـ normal clock - هذه من الـ optimization التى يتيحها المعالج، أيضا عند تنفيذ loop معين سرعة التنفيذ فى البدايه تختلف تماما عنها فى المنتصف و النهايه و ذلك لأنه يتم إجراء fetch لكل عناصر الحلقه داخل الـ cache - على اعتبار ان الـ loop صغير - حينها التعامل يكون داخليا بالبروسسور و بالتالي لا يتم التعامل مباشرة مع الـ RAM و إنما مع الكاش أيا كانت درجتها و عندما نتكلم عن تنفيذ عملية مثل xor eax, eax سترى أن سرعة التنفيذ تأخذ clock واحده فقط. نفس الكلام ينطبق عند تنفيذ كود النسخ حيث نقوم بنقل البيانات إلى الكاش الأقرب للمعالج - الداخلي - و ذلك حتى تكون سرعة النسخ أعلى و ذلك بسبب ان التعليمات تأخذ وقت اقل فى التنفيذ.

لاحظ ايضا ان الـ motherboard تحتوى ايضا على cache و ذلك لتقليل الوقت الخاص بالوصول للذاكره و بالتالي إذا تسألت هل يمكن ان يتم تنفيذ تعليمه ما فى 1 clock الإجابه ستكون نعم، و إذا كان سؤالك هو هل الوقت المستغرق فى الوصول للتعليمه و تنفيذها يستغرق 1 clock حينها تكون الإجابه محتمل حيث وقتها سنحتاج للتأكد من عدة عوامل و حتى هذه العوامل ستختلف بإختلاف نوع المعالج و نوع الذاكره و نوع اللوحه الأم.

و الله ولي التوفيق

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

كلامك صحيح و لكن توجد فقره تحدد كيب تقوم بحسابها، فى كتاب Volume 3B: System Programming Guide, Part 2 الفصل 30 بعنوان Performance Monitoring الفقره رقم 10 بعنوان Counting Clocks تشرح لك بالتفصيل كيف تحسب عدد الـ clocks لأى تعليمه - أو تعليمات (زمن تنفيذ جزء معين من الكود) - و ايضا تحدد لك كيف تحصل عليها بدقه كبيره و ذلك بتلاشى النقاط التى قد تسبب إرجاع قيم غير صحيحه و كتطبيق على هذه النقطه داخل كتاب CPUID instruction اخر جزء منه الخاص بمثال حساب سرعة البروسسور عن طريق إستخدام RTSC و هي احد الطرق التى يتم شرحها فى الفقره رقم 10 المذكوره بالأعلي.

أيضا يحدد كتاب Volume 3B: System Programming Guide, Part 1 الفصل 16 بعنوان Debugging, Profiling Branches and Time- Stamp Counter الفقره 16 بعنوان Time-Stamp Counter يقال بها ان قيمة الـ Time-Stamp Counter تختلف بإختلاف المعالج فبأحدهم يتم تحديثها تبعا لـ normal clock و بأخر تبعا للـ internal clock.

عندما تقوم بكتابة تعليمات غير مرتبطه ببعضها حينها يقوم المعالج بتنفيذهم بشكل متوازى - فيما يظهر لنا أو تبعا للـ normal clock - هذه من الـ optimization التى يتيحها المعالج، أيضا عند تنفيذ loop معين سرعة التنفيذ فى البدايه تختلف تماما عنها فى المنتصف و النهايه و ذلك لأنه يتم إجراء fetch لكل عناصر الحلقه داخل الـ cache - على اعتبار ان الـ loop صغير - حينها التعامل يكون داخليا بالبروسسور و بالتالي لا يتم التعامل مباشرة مع الـ RAM و إنما مع الكاش أيا كانت درجتها و عندما نتكلم عن تنفيذ عملية مثل xor eax, eax سترى أن سرعة التنفيذ تأخذ clock واحده فقط. نفس الكلام ينطبق عند تنفيذ كود النسخ حيث نقوم بنقل البيانات إلى الكاش الأقرب للمعالج - الداخلي - و ذلك حتى تكون سرعة النسخ أعلى و ذلك بسبب ان التعليمات تأخذ وقت اقل فى التنفيذ.

لاحظ ايضا ان الـ motherboard تحتوى ايضا على cache و ذلك لتقليل الوقت الخاص بالوصول للذاكره و بالتالي إذا تسألت هل يمكن ان يتم تنفيذ تعليمه ما فى 1 clock الإجابه ستكون نعم، و إذا كان سؤالك هو هل الوقت المستغرق فى الوصول للتعليمه و تنفيذها يستغرق 1 clock حينها تكون الإجابه محتمل حيث وقتها سنحتاج للتأكد من عدة عوامل و حتى هذه العوامل ستختلف بإختلاف نوع المعالج و نوع الذاكره و نوع اللوحه الأم.

و الله ولي التوفيق

اذا كنت تقصد بالتسريع الpipeline فهذا التكنيك لايقلل من مدة التعليمة وانما يستغل الفراغات slots فحينما تنتقل التعليمة الاولي من fetch الى execute لا تنتظر التعليمة الثانية انتهاء التعليمة وانما تدخل في مرحلة fetch حالما تدخل التعليمة الاولى في مرحلة execute

اما اذا كنت تقصد المعالجة المتوازية ، فأنها لن تتطبق الا في حالة كان هناك enable لاسلوب الhyberthreading في حالة معالجات بانتيوم 4 او ان يكون البرنامج مكتوب باسلوب multithreaded سوءا بOpenMP,Open MPI, PThread او غيره وهذه مسؤلية المبرمج وليست مسؤلية المعالج، فلا يستطيع المصنع ان يضمن لك هذا up front

طيب تعال نفكر انا وانت مع بعض

متفقين ان اي جهاز كمبيوتر ذو غرض عام يتبع معمارية فو نيومان صح؟

تمام ، لنفرض ان البرنامج كملف ثنائي binary موجود في الذاكرة ولحظة تنفيذ البرنامج يحمل في الذاكرة، الان لنقل ان مؤشر التعليمة Instruction Pointer يشير الى تعليمة معينة

لنفترض بغرض السهولة ان هذه التعليمة شفرتها على الشكل التالي


0xFFAB

لنفرض ان هذه التعليمة على الشكل ، الحرف الهيكس الاول يشير الى التعليمة ، والثلاث الحروف الهيكس الباقية تشير الى عنوان الذاكرة


OPCODE ADDRESS

اي تستخدم العنونه المباشرة ، تمام؟

الان عندما يريد البرنامج تنفيذ هذا الامر عليه اولا ان يحمل الامر من الذاكرة

لعمل هذا

1- نحمل سجل العناوين بمؤشر التعليمة


AR <- PC

2- نقوم بقراءة عنوان الذاكرة الذي يشير اليه سجل العناوين الى داخل سجل البيانات Data Register


DR <- M[AR]

3- يقوم المعالج بتفكيك هذا الامر بحيث يقوم بايداع اول اربع ثنائيات بداخل سجل الاوامر Instruction Register(Control Unit) ليتم تفسير نوع الامر

ويتم ايداع الاثنى عشر ثنائية الاخرى في سجل العناوين ، حيث هذا العنوان هو عنوان البيانات التي نريد جلبها من الذاكرة

4- لنقل ان الامر هو تحميل محتوى الذاكرة الى داخل السجل في هذه الحالة سوف نقوم بقراءة محتوى الذاكرة الى داخل السجل مباشرة


EAX <- M[AR]

هذا مثال افتراضي مبسط لعمل المعالج ، سؤالي هل يمكن اختصار هذه الخطوات كلها في خطوة واحدة؟

اذا كان هذا ممكنا اذا يمكن ان نحصل على تعليمة يتم تنفيذها في نبضة ايقاع واحدة

او السؤال بطريقة اخرى : هل من الممكن صنع ASM chart لFSM توجد بها حالة واحدة فقط تمثل العمليات المذكورة بالاعلى؟

اسف على الاطالة

تم تعديل بواسطه mental-driller
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

على سبيل المثال:


mov eax, [ebp - 4] ; 8B 45 FC

أخى انت تفترض ان المعالج عندما يصل لمثل هذه التعليمه انه اثناء تنفيذها سيذهب إلى الذاكره للحصول على القيمه المقابله لـ ebp - 4 و بعدها يكمل فى مسار عمله و هذا سيؤدى ان التعليمه تأخذ اكثر من clock و هذا خطأ بكل تأكيد.

المعالج يحتوى على instruction pipeline و التى تمثل عدة مراحل لتنفيذ التعليمه كل مرحله منفصله عن الأخرى اى يمكنك القول انه يتم تنفبذهم بشكل متوازى، عائلة المعالجات i486 تحتوى على 5 مراحل و المعالج pentium 3 يحتوى على 10 مراحل و معالجات pentium M تحتوى من 12 إلى 14 مرحله و المعالج pentium 4 تحتوى على 14 مرحله و الجيل السادس من معالجات انتل يحتوى على 14 مرحله محسنه.

هذه المعالجات تستطيع تنفيذ 14 عملية - و ليس تعليمه - فى خطوه واحد، و بالنسبه للكود بالأعلي فما سيحدث هو ان المعالج سيقوم بالتالي:

1- الحصول على التعليمه - بمعاملاتها - من الذاكره.

2- الحصول على القيمة المقابله من العنوان ebp-4 من الذاكره و فى نفس الوقت تحويل التعليمه إلى صيغة RISC و ذلك للتنفيذ.

3- تنفيذ التعليمه، عملية التنفيذ لن تأخذ اى وقت و ذلك لأن القيمه التى يحتاجها من الذاكره موجوده بالفعل داخل الكاش و بالتالي عملية الـ mov لأن تأخذ أكثر من clock cycle.

إن وجدت عملية كتابة فى الذاكره سيقوم المعالج بجعل DMA controller يقوم بالمهمه و سيكمل هو عمله و عند و صول الإشاره من الـ DMA سيكون رد فعل المعالج يتناسب مع النتيجه ذاتها.

داخل كتاب Art Of Assembly DOS Edition الفصل الثالث بعنوان System Organization الفقره رقم 3.3.12.1 بعنوان The 8486 Pipeline يقوم بشرح عملية تنفيذ التعليمات كما كان يحدث فى تلك المعالجات، هذه الفقره ستعطيك فكره عامه عن الكيفيه التى تتم بها عملية التنفيذ.

ايضا رجوعا لعام 1990 وجدت مقال بموقع IEEE يتحدث عن معالجات Intel i486 التى تقوم بتنفيذ تعليمه مع كل clock cycle، و هذا هو الملخص لهذه المقاله: (لاحظ انها تعود لـ 21 سنه ماضيه)

The integer instruction execution pipeline of the Intel i486 processor is described. The performance of the i486 CPU in a system is related to several systems based on competitive reduced-instruction-set-computer (RISC) processors. The instruction pipeline was designed to execute instructions at a sustained rate of 1 clock per instruction. A key to achieving this rate was the integration of the cache into the pipeline. Another key was pipelining the instruction decoder into two stages to provide a sustained throughput of 1 instruction per clock, while decoding the complex instruction formats of the Intel 386 family architecture. An overview of the pipeline is provided by giving a brief description of each pipeline stage. Then several multiple instruction examples are given to illustrate some key properties of the pipeline

لاحظ ان الكلمه clock per instruction لا تتساوى إطلاقا مع الكلمه instruction per clock حيث الأولي تعنى عدد الـ clocks التى نحتاجها لتنفيذ تعليمه واحده اما الأخيره فتعنى عدد التعليمات التى يتم تنفيذها فى clock واحده، على الرغم من ذلك فداخل الملخص بالأعلي الكلمتين لهما نفس المعنى لأنه تم تحديد عدد الـ clocks الذى تحتاجه التعليمه حتى يتم تنفيذها و هو 1 (الجزء الموجود تحته خط).

و الله ولي التوفيق

تم تعديل بواسطه محمد علاء الدين
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

في شرحك قمت بتفصيل دورة الامر الى ثلاث مراحل ،

ممكن توضح لي ازايج انت حتدمج دورة الامر كلها في نبضة ايقاع واحدة

حتى باستخدام الpipeline ، انا فاهم انو انت قصدك انه المعالج لما بيوصل لتنفيذ الامر بيكون الامر تم احضارة مسبقا من الذاكرة

بس الاحضار بيتم في نبضة ايقاع سابقة مع امر اخر

حاولت ان اقرأ المقالة ولكن الظاهر انها مجرد abstract

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

انا أتكلم عن الوقت المستغرق فى تنفيذ التعليمه فقط و لاحظ حتى فى الإقتباس قيل:

The instruction pipeline was designed to execute instructions at a sustained rate of 1 clock per instruction.

هذه ما اريد توضيحها، و مثل ما قلت لك فى مشاركه بالأعلي:

إذا تسألت هل يمكن ان يتم تنفيذ تعليمه ما فى 1 clock الإجابه ستكون نعم، و إذا كان سؤالك هو هل الوقت المستغرق فى الوصول للتعليمه و تنفيذها يستغرق 1 clock حينها تكون الإجابه محتمل

إذا كان يوجد أمر لا افهمه فيرجي منك توضيحه.

و الله ولي التوفيق

تم تعديل بواسطه محمد علاء الدين
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

وضحت الفكرة يا عزيزي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

نقاش برمجي رائع جدا و يحتوي على معلومات برمجية راقية :cool:

+++++++++++

هل يمكننا العودة إلى الموضوع الأصلي ؟ :lol:

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

عفوا على تحوري للموضوع، والله محرج منك

و لا يهمك عزيزي :)

النقاش كان له علاقة بالموضوع, و إن لم تكن علاقة مباشرة و لكنها في الأخير تبقى علاقة, أضف إلى ذلك أن النقاش كان مليئا بالمعلومات البرمجية الراقية و الرفيعة المستوى مما يُثري من قيمة الموضوع و هذا هو هدفنا المنشود :happy:

الآن, أرجو منك أنت و بقية الإخوة الكرام أن تفتحوا لنا نقاشا جديدا, تكون علاقته بالموضوع مباشرة و كل يُدلي دلوه لنُثري الموضوع مُجددا و تعم الفائدة :wink:

اقتراح :

ما رأيكم أن يكون هذا الموضوع متخصص في إيضاح الأشياء التي عادة ما يصعب فهمها على المبتدئين,المتوسطين أو حتى المحترفين :wink: و بهذا يكون هذا الموضوع جامعا للكثير من الكنوز التي يمكن أن تتناثر في مواضيع مختلفة .. مما يُشتت ذهن الزائر و يقلل من الإستفادة !

أقترح أن يضع العضو (أول مجيب على السؤال المطروح) فائدة جديدة و يضع خلاصة القول بعد انتهاء النقاش لتكون تلك الخلاصة ختام مسك للقضية السابق نقاشها و هكذا دواليك ...

بالتوفيق.

تم تعديل بواسطه أحمد المتألق
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .