إنه لمن دواعي سروري أن أشبع رغباتي ، خاصةً من الماضي البعيد ، لدرجة أني نسيت أنني أردت ذلك من قبل. لا أعرف الكثير عن الديموزين وأنا بالتأكيد لم أتابع المؤلفين أو عملهم ، أحببت أن أشاهد ما حدث. في بعض الأحيان كنت أرغب في معرفة ذلك ، ولكن بعد ذلك افتقرت إلى المعرفة والخبرة ، والمثابرة لاحقًا ، ثم فقدت الاهتمام تمامًا بهذا. ولكن في الآونة الأخيرة ، قام صديقي ، الذي درسنا معه في ذلك الوقت والذي زودنا بجميع المنتجات الجديدة ، بما في ذلك العروض التوضيحية ، مع BBS و Fidonet ، نظرًا لأنه كان لديه هاتف ومودم وجهاز كمبيوتر في نفس الوقت تقريبًا ، قام بزيارة
CAFePARTY مع عمله الذي جعلني أفتح أرشيف جهاز الكمبيوتر الأول الخاص بي ، حدد عرضًا تجريبيًا واكتشفه.
بتقييم موضوعي لقوتي ، أخذت مقدمة 128 بايت والتي أعجبت بها بصريًا. تم توقيع ملف pentagra.com بواسطة
Mcm ، 128 بايت ، آخر تعديل 9/24/1996 18:10:14 ، عرافة تفريغ:
000000: b0 13 cd 10 68 00 a0 07 06 1f ac ba c8 03 ee 42
000010: b1 40 ee 40 6e 6e e2 fa b8 3f 3f bb 40 01 bf 40
000020: 05 57 b1 78 ab 03 fb e2 fb 5f b1 60 88 01 aa 03
000030: fb 03 fb e2 f7 b1 61 88 01 aa 2b fb 2b fb e2 f7
000040: bf d1 99 57 b1 78 ab 2b fb e2 fb 5f b1 8f f3 ab
000050: 81 fe 00 fa 73 12 ac 0a c0 74 0d 48 88 44 fe 88
000060: 04 88 40 ff 88 84 bf fe 03 f2 42 75 e3 e4 60 3c
000070: 01 75 a5 b8 03 00 cd 10 c3 00 00 00 00 4d 63 6d
من نفس الأرشيف انسحبت:
- Hiew 6.11 (يمكن العثور على 6.50 على الموقع) - لقد استخدمته كمفكك
- حزمة TASM - التي جمعت بها الكود الذي تم استلامه مرة أخرى للتأكد من أنني لم أحبط أي شيء
- مساعدة فني Flambeaux البرمجيات! 6.0 - مرجع عبر الإنترنت مفصّل وشامل لواجهة برمجة تطبيقات DOS ووظائف BIOS والأجهزة والتجميع
- مايكو جي في مجمع لأجهزة IBM PC - مرجع تنسيق بحجم الجيب تقريبًا لجميع أوامر Intel 8086 الأساسية وقواعد تنسيق نص البرنامج. بدون تفاصيل معمارية ومع أمثلة أولية ، فقط الأشياء الأساسية. يوجد كل ما تحتاجه هنا تقريبًا ، لكن لا يمكنك الكتابة في مجمّع ما عدا البيئة.
- لذلك ، فإن الكتاب الثاني Zubkov S.V. المجمع. لدوس ، ويندوز ، ويونيكس - دليل للأجهزة الزوايا و DOS
من الحد الأدنى للتنفيذ ، ينبغي للمرء أن يتوقع استخدام الحيل والأساليب غير القياسية ، ولكن بصرف النظر عن بعض الافتراضات في الظروف الأولية ، لم أر أي حيل فنية ، لكنني رأيت حيلة حسابية. وهنا بعض الكلمات يجب أن تقال عن التجربة. ماذا يمكن أن تكون الصعوبة؟ إما في التنفيذ أو في الخوارزمية. على سبيل المثال ، في الأمر
mov di, 099d1h
، قد تكون خائفًا من الثابت السحري. ولكن إذا كنت في سياق الاستخدام ، يصبح من الواضح أن هذا هو عنوان الوصول على الشاشة وينسق X و Y ، حيث X = 17 ، Y = 123 ، 320 هي الدقة الأفقية للشاشة بالبكسل. يمنحك هذا معًا 17 + 123 * 320 ، تحويل الإحداثيات ثنائية الأبعاد إلى أحادية البعد.
بالنظر الآن إلى ما يحدث على الشاشة ، يمكنني أن أتخيل بسهولة كيف يمكنني تنفيذ ذلك ، وإن لم يكن مع 128 بايت ، حتى لو لم تكن متشابهة بنسبة 100 ٪ ، ولكن يمكنني ذلك. وقبل 20 عامًا ، لم أستطع ذلك ، على الرغم من أنني سحبت جميع الأدوات التي استخدمتها من الأرفف المتربة ولم أضطر إلى تصفح الإنترنت لفهم كيفية عملها. لذلك ، بادئ ذي بدء ، هذا هو السياق ، وفهم ما يحدث ، وبالتالي فإن مسألة الحيل وكيف نفعل ذلك في المرتبة الثانية.
ماذا نرى:
- 5 خطوط من الخماسي. هذه ليست بالضرورة خطوط لا تنفصم مباشرة وفقا لجميع الشرائع. نرى فقط الرقم العام ، دون تفاصيل
- تأثير اللهب ، الذي يتكون من جزأين مهمين: لوحة محددة بشكل صحيح وخوارزمية لتغيير لون النقاط على الشاشة باستمرار مع عناصر من عدم اليقين ، مع الحفاظ على تسلسل لوحة مستمر للنقاط المجاورة. على سبيل المثال ، يمكنك حساب الشاشة الحالية بأكملها عن طريق حساب متوسط قيم البيكسلات المجاورة من الشاشة السابقة ، وإضافة المزيد من النقاط "الساطعة" في أماكن عشوائية ، أو ليس في أماكن عشوائية ، ولكن عشوائية في القيمة ، أو لا على الإطلاق بالمصادفة ، ما عليك سوى الابتعاد عن الترتيب الخطي. خيار واحد هو كيف يتم ذلك في DOOM . يجب أن تكون النتيجة في شكل ألوان تتدفق إلى بعضها البعض ، من المساحات المشرقة الناشئة باستمرار إلى الخبو
يبقى أن نفهم كيف تم ذلك. لن يحل الوصف الإضافي محل المعرفة حول بنية الكمبيوتر ووظائف DOS أو المجمّع ، لكن امتلاك هذه المعرفة سيسمح لك بفهم جوهر ما يحدث والتركيز عليه. بعد أن بدأت في الكتابة ، أدركت أن كل هذا يظهر بتفاصيل كافية ، لكنني لم أستطع رفضه حتى لا أخسر بمعنى القصة.
دوس وتحميل برامج .COM
البرنامج الموجود في ملف
.com
هو رمز نظيف ، بدون رؤوس ، كل ما تحتاجه هو وضعه في المكان المناسب. هذا هو ما يفعله DOS ، أو بالأحرى استدعاء نظام 4Bh. الكثير من الإجراءات تجري ، دعونا نتحدث عن النتيجة:
- جميع القطاعات تسجل CS ، DS ، ES ، SS محملة بقيمة واحدة
- 65536 بايت محجوزة للبرنامج بأكمله ، بالضبط قطعة واحدة تشير إليها جميع سجلات القطاع. أول 256 بايت مشغولة بواسطة رأس النظام - PSP (بادئة شريحة البرنامج). في CS: 0 ، الحقل الأول من PSP ، يوجد الأمر INT 20h - لإنهاء البرنامج الحالي ونقل التحكم إلى العملية الأصل. يبدأ البرنامج نفسه بعنوان CS: 100h ويحتل 128 بايت التالية
- يتم دفع الكلمة 0000h على المكدس ، وسجل SP هو FFFEh. هذا يعني أنه تم إعادة تعيين آخر وحدتي بايت في هذا الجزء على العنوان SS: FFFEh. في الواقع ، هذا هو أقرب عنوان إرجاع من الإجراء ، والذي سيقودنا إلى أمر الإكمال في CS: 0
- تحتوي سجلات AL و AH على علامة خطأ لتحديد أحرف محركات الأقراص من الوسيطة الأولى والثانية عند استدعاء البرنامج. إذا لم تكن هناك أخطاء ، فعندئذٍ تكون 0 ، وإذا كان هناك FFh
اعتقدت بصدق أنه في الحالة العامة لم يتم تحديد حالة السجلات. ولكن في الشفرة التي تم تحليلها ، في رأيي ، يتم فرض افتراض جريء للغاية حول حالتهم الأولية ، خاصة حول سجلات CX و SI وعلم اتجاه DF. لم أجد تأكيدًا لهذا في قائمة المصادر التي نتجت عنها أعلاه ، لذلك ذهبت للبحث في مصادر
MS-DOS 2.0 :
- حول DF ، يمكننا أن نفترض أنه تمت إعادة تعيينها بواسطة الأمر
cld
، لأن الأخير يستخدم الاتجاه الأمامي قبل نقل التحكم إلى cld
الأسطر ، لذلك ، تتم إعادة تعيين DF. على الرغم من عدم وجود استخدام صريح لـ cld
في هذا المكان ، إلا أنه يتم مواجهة الأمر لمسح cld
الاتجاه في كثير من الأحيان قبل العديد من عمليات النقل الأخرى - يحتوي SI على 100 ساعة ، لأنه يستخدم لتحديد الإزاحة التي سيتم تحميلها في السجل بواسطة عداد أوامر IP
- CX تساوي FFh ، لأنه يستخدم كعداد عداد بقيمة أولية من 80h لنقل محتويات سطر الأوامر بأكمله ، وبالتالي ، بعد نقله هو 0. وبعد ذلك ، يقوم CL ، كمتغير مؤقت ، بتحميل FFh ويستخدم لتعيين علامة خطأ حرف محرك الأقراص في AL و AH
لا توجد مصادر للإصدارات الأحدث ، ولكن توجد
مصادر DOSBox :
reg_ax=reg_bx=0;reg_cx=0xff; reg_dx=pspseg; reg_si=RealOff(csip); reg_di=RealOff(sssp);
بمعنى أنه يتزامن مع ما رأيته في التعليمات البرمجية المصدر لـ MS-DOS (الإصدار الثاني!) ، يمكنك رؤية القيم الأولية للسجلات الأخرى ، ومن هنا تهيئة صريحة خاصة. بالنسبة إلى MS-DOS ، تعد قيم السجلات بخلاف AX ، والمقطع ، والمكدس أساسيات لاستخدامها لأغراض أخرى ؛ وهذا ليس عقيدة أو معيارًا ، وبالتالي ، لم يتم ذكرها في أي مكان. ولكن من ناحية أخرى ، أصبح النظام البيئي الذي تشكله والألم الكامل لمايكروسوفت في دعم التوافق مع الإصدارات القديمة ، مما يضطر إلى التراجع عن القيم التي تم إنشاؤها عشوائيًا ، أمرًا مفهومًا إلى حد ما ، لأن المبرمجين معتادون عليهم.
أخيرًا ، بالنسبة لنا هذه المعرفة كافية ، نبدأ في استعادة البرنامج من الرؤوس:
.186 .model tiny .code .startup
نحدد نوع المعالج 80186 ، لأننا نستخدم الأمر
outsb
، الذي ظهر فقط في هذا النموذج. مقطع شفرة واحد ونقطة إدخال للبرنامج ، والتي ، بالإضافة إلى تعريف طراز الذاكرة
tiny
، سوف تسمح للمترجم بحساب جميع إزاحات المتغيرات والانتقالات بشكل صحيح. عند إنشاء
tlink
،
tlink
استخدام رمز
tlink
/t
؛ في الإخراج هذا سيعطي ملف
.com
.
الرسومات ولوحة
للتبديل إلى وضع الرسوم ، يجب أن تنتقل إلى وظيفة BIOS ، والتي يطلق عليها مقاطعة 10 ساعات ، AH = 0 ، في AL نضع معرف الوضع المرغوب - 13 ساعة:
mov al, 13h ;b0 13 int 10h ;cd 10
يرجى ملاحظة أننا لا نلمس AH ، على افتراض أن هناك الصفر ، وفقا لشروط تحميل البرنامج. يتوافق الوضع المحدد مع دقة رسومات تبلغ 320 × 200 بكسل مع لوحة ألوان 256. لعرض نقطة على الشاشة ، تحتاج إلى الكتابة إلى منطقة الذاكرة ، والتي تبدأ بعنوان A000h: 0 ، البايتة المقابلة للون. املأ سجلات بيانات القطاع بهذه القيمة:
push 0a000h ;68 00 a0 pop es ;07 push es ;06 pop ds ;1f
منطقيا ، يتم تنظيم الذاكرة كصفيف ثنائي الأبعاد يتم عرض إحداثيات الشاشة فيه ، 0: 0 يتوافق مع الزاوية اليسرى العليا. بعد تبديل الوضع ، يتم ملؤه بالأصفار - أسود في اللوحة الافتراضية. صيغة الترجمة إلى الإزاحة الخطية هي
X + Y * L ، حيث L هي الدقة الأفقية ، في حالتنا 320. في هذا النموذج ، سأكتب في تلك الأماكن التي تُستخدم فيها الثوابت ، عند ترجمة نص البرنامج يتم حسابها تلقائيًا.
لتغيير اللوحة ، نصل مباشرة إلى الجهاز باستخدام منافذ الإدخال / الإخراج:
lodsb ;ac mov dx, 03c8h ;ba c8 03 out dx, al ;ee
يتم تحميل الأمر الأول إلى AL ، بايت البيانات الموجود في DS: SI. في DS ، قمنا بتحميل عنوان مقطع ذاكرة الفيديو ونعلم أنه مليء بالأصفار ، في SI - في الحالة العامة ، من غير المعروف أنه على الأقل 0. لا يهمنا أينما تشير SI ، فإننا ندخل بالتأكيد في ذاكرة الفيديو التي تشغلها مع هذا القرار 320 * 200 = 64000 بايت ، الجزء بأكمله تقريبا. وبالتالي ، فإننا نتوقع بعد هذا الأمر AL = 0. تتم إضافة وحدة أو طرحها على SI ، وذلك يعتمد على إعداد علامة الاتجاه DF. على الرغم من أن هذا ليس مهمًا بشكل خاص بالنسبة لنا ، بغض النظر عن مكان تحرك SI ، فإننا لا نزال في منطقة ذاكرة الفيديو المليئة بالأصفار.
بعد ذلك ، قم بتحميل DX برقم المنفذ 03C8h ، حيث يحدد المخرجات اللون 256 الذي سنقوم بتجاوزه. في حالتنا ، يكون 0 من AL.
يتم تشفير اللون في لوحة RGB ، ولهذا يجب عليك الكتابة إلى المنفذ 03C9h (واحد أكثر من 3C8h) ثلاث مرات على التوالي ، مرة واحدة لكل مكون. أقصى سطوع المكون هو 63 ، والحد الأدنى هو 0.
inc dx ;42 mov cl, 64 ;b1 40 PALETTE: out dx, al ;ee inc ax ;40 outsb ;6e outsb ;6e loop PALETTE ;e2 fa(-6), 6
قم بزيادة DX بواحد بحيث يحتوي على رقم المنفذ المطلوب. CL هو عداد دوراتنا وهو 64 ، ونحن نفترض أن CH = 0 ، كما هو موضح سابقًا بناءً على شروط التحميل الأولية. بعد ذلك ، نقوم بإخراج المكون الأول للمنفذ - المكون الأحمر الذي سيتم تخزين سطوعه في AL ، وهو أننا سنتغير في الخطوة الأولى 0. وبعد ذلك نقوم بزيادة السطوع بواحد لعرضه في التكرار التالي. بعد ذلك ، نقوم بتنفيذ أمرين
outsb
إلى المنفذ ، الذي يرد
outsb
في DX ، البايتة من منطقة ذاكرة DS: SI ، تذكر أن لدينا أصفارًا هناك. SI يتغير كل مرة واحدة.
بمجرد استنتاجنا للمكونات الثلاثة ، تتم إضافة وحدة تلقائيًا إلى رقم اللون. وبالتالي ، ليس من الضروري إعادة تعريف اللون عن طريق الإخراج إلى منفذ 3C8h إذا كانت الألوان في صف واحد ، كما هو مطلوب. سيقلل الأمر
loop
من CX بواحد ، إذا تم الحصول على قيمة غير صفرية ، فسيتم الانتقال إلى بداية الدورة ، إذا كانت 0 ، ثم إلى الأمر التالي بعد الدورة.
ما مجموعه 64 التكرار. في كل تكرار ، نحدد للون ، بدءًا من 0 إلى 63 ، المكون الأحمر ذو السطوع يتزامن مع رقم اللون الحالي. نحن نعيد ضبط المكونات الخضراء والزرقاء للحصول على هذه اللوحة من الحد الأدنى إلى الحد الأقصى من السطوع الأحمر:
خطوط
قم بإعداد اللون الأولي وتنسيق القيم:
LINES: mov ax, 03f3fh ;b8 3f 3f mov bx, 0+1*320 ;bb 40 01 mov di, 64+4*320 ;bf 40 05 push di ;57
في AL و AH نقوم بتحميل الحد الأقصى الممكن (اللامع) للون 63 (3Fh) ، على التوالي ، AX يحدد نقطتين في وقت واحد. BX - الدقة الأفقية القصوى. في المستقبل ، سيتم استخدام هذا لإضافة أو طرح سطر واحد من الإحداثيات الحالية. DI - الإحداثيات 64: 4 ، حفظها على المكدس.
ارسم السطر الأول من الزاوية اليسرى العليا إلى أقصى اليمين :
mov cl, 120 ;b1 78 LINE1: stosw ;ab add di, bx ;03 fb loop LINE1 ;e2 fb(-5)
تكوين العداد - هذا سيكون عدد الخطوط. بعد ذلك ، احفظ الكلمة (وحدتي بايت) من AX إلى العنوان ES: DI. سيعرض هذا الإجراء نقطتين على الشاشة مع الحد الأقصى للون من لوح الألوان لدينا ، لأن ES تم تكوينه لذاكرة الفيديو ، ويتم تعيين إحداثيات محددة في DI. بعد هذا الإجراء ، ستتم إضافة 2 إلى DI ، حيث تم كتابة وحدتي بايت. من الواضح أننا لا نضع علامة اتجاه DF ونعتمد على حقيقة أنه قد تمت إعادة تعيينه ، مرة أخرى ، نذكر بشروطنا الأولية لتحميل البرنامج. خلاف ذلك ، سيتم أخذ الاثنين بعيدا ، والتي لن تسمح رسم الخط المطلوب.
بعد ذلك ، DI = DI + BX ، أي ما يعادل زيادة إحداثي Y بواحد. وهكذا ، في جسم الدورة ، يتم رسم نقطتين في سطر واحد ، ويتم زيادة إحداثي X بمقدار 2 ، والإحداثي Y بمقدار 1 ويتم تكرار هذا الإجراء 120 مرة ، وتكون الصورة مع النتيجة أقل قليلاً.
السطر الثاني هو من أعلى اليسار إلى الأعلى :
pop di ;5f mov cl, 96 ;b1 60 LINE2: mov [bx+di], al ;88 01 stosb ;aa add di, bx ;03 fb add di, bx ;03 fb loop LINE2 ;e2 f7(-9)
نستعيد الإحداثيات الأولية 64: 4 ونضبط العداد على 96 تكرار. نطبع نقطة واحدة ، لكن سطر واحد أسفل الإحداثيات الحالية. كما كان من قبل ، يتم تحقيق ذلك عن طريق إضافة قيمة من BX ، فقط دون حفظ الإحداثيات الجديدة. يسمى الإنشاء
[bx+di]
أو
[bx][di]
بـ العنونة الأساسية بالفهرسة ويعمل على مستوى المعالج وليس المترجم. تسجيل قطعة الافتراضي مع BX هو DS. بعد ذلك نعرض النقطة الثانية ، ولكن بالفعل في الإحداثيات الحالية. DI ، وبالتالي يزيد X بمقدار واحد ، حيث يتم
stosb
أمر نقل بايت واحد فقط -
stosb
. آخر أمرين لجسم الدورة هما زيادة Y بمقدار 2 ، والتي نستخدم BX لها مرة أخرى.
بعد رسم سطرين ، يتم الحصول على الصورة التالية بالقرب من الزاوية اليسرى العليا:
إحداثيات اليسار وأعلى ، يمين عنوان إزاحة السطر في ذاكرة الفيديو. سيتم رسم النقطة 64: 4 مرتين.
السطر الثالث من الأعلى إلى الزاوية اليمنى العليا :
mov cl, 97 ;b1 61 LINE3: mov [bx+di], al ;88 01 stosb ;aa sub di, bx ;2b fb sub di, bx ;2b fb loop LINE3 ;e2 f7(-9)
تحتوي DI بالفعل على قيمة الإحداثيات المرغوبة 160: 196 ، نحتاج إلى رسم خط من الأعلى حيث انتهى السطر السابق ، مع تحريك الشاشة لأعلى مع الحفاظ على نفس الزاوية. وفقا لذلك ، فإن الدورة متطابقة تقريبا. يتم زيادة CX بمقدار 1 ، نظرًا لأن الإحداثي الحالي Y هو 2 (أقل) من حيث انتهى السطر السابق ، تم حسابه بالفعل للتكرار التالي. لذلك ، للوصول إلى الزاوية العليا ، تحتاج إلى اتخاذ خطوة إضافية. تستمر الحركة على طول X في نفس الاتجاه - بالإضافة إلى واحدة بعد كل تكرار ، وعلى طول Y ، بدلاً من الإضافة ، نقوم بطرح الاثنين. يتم عرض النقاط في نفس الترتيب ، أولًا أقل ثم أعلى.
السطر الرابع من أقصى اليسار إلى الزاوية اليمنى العليا: mov di, 17+123*320 ;bf d1 99 push di ;57 mov cl, 120 ;b1 78 LINE4: stosw ;ab sub di, bx ;2b fb(-5) loop LINE4
نحن مرة أخرى في الإحداثيات اللازمة ، ولكن هذا لا يستخدم ، على ما يبدو من أجل عدم تغيير إشارة الاتجاه DF. لذلك ، يتم وضع إحداثيات جديدة في DI وتخزينها على المكدس.
علاوة على ذلك ، كل شيء مماثل للسطر الأول ، فقط تنسيق Y لا ينمو ، ولكن النقصان ، نرتفع.
السطر الخامس أفقي: pop di ;5f mov cl, 143 ;b1 8f rep stosw ;f3 ab
كل شيء بسيط هنا ، يتم استخدام آلية إعادة الإرسال المعالج الدقيق ، لأن الخط الأفقي يتوافق مع زيادة بسيطة في عنوان كل نقطة التالية. في DI ، تتم استعادة العنوان المطابق لإحداثيات الزاوية القصوى اليسرى ، المخزنة في الخطوة السابقة. يتم تعيين عدد التكرارات في CX ويتم تطبيق بادئة التكرار مع أمر word transfer.
بعد هذا الإجراء ، لدينا رسم خماسي مرسوم بالكامل بألوان زاهية. 80 بايت المستخدمة و 48 في الاحتياطي.
سحر النار
وضعنا شروط الحدود للحسابات: FLAME: cmp si, 320*200 ;81 fe 00 fa jae NEXT_PIXEL ;73 12 lodsb ;ac or al,al ;0a c0 jz NEXT_PIXEL ;74 0d
في SI سيكون هناك إحداثي للنقطة الحالية للحسابات ، إذا تجاوزنا حدود الشاشة ، فلن نقوم بأي عمليات حسابية بهذه النقطة ، ننتقل إلى حساب النقطة التالية.
lodsb
بتحميل بايت من منطقة DS: SI إلى AL ، أي لون النقطة في الإحداثيات الحالية. إذا كانت 0 ، فإننا أيضًا لا نفعل شيئًا وننتقل إلى النقطة التالية.
حساب لون جديدهذه هي الخوارزمية الرئيسية لتغيير قيم اللون على الشاشة ، هذه ليست لهب ، هذا هو الأساس لها. نحسب النقاط المجاورة ونحقق استمرارية اللون:
dec ax ;48 mov [si-2], al ;88 44 fe mov [si], al ;88 04 mov [bx+si-1], al ;88 40 ff mov [si-1-1*320], al ;88 84 bf fe
اطرح من AX ، في الواقع من AL ، وحدة تحتوي على قيمة ألوان غير صفرية تم الحصول عليها من الإحداثيات الحالية. بعد ذلك ، نقوم بتدوين القيمة التي تم الحصول عليها لجميع النقاط المجاورة ، بالنسبة إلى الإحداثيات الحالية ، أي القليل منها ، بناءً على لوحة الألوان الخاصة بنا.
نظرًا
lodsb
بعد
lodsb
، زادت قيمة SI بمقدار واحد ولم تعد تتوافق مع النقطة التي نقرأ فيها اللون في AL ، ويجب تعديل ذلك. لاحظ أن أوامر نقل بايت
stosb
لم تعد مستخدمة ؛ بدلاً من ذلك ، يتم استخدام
mov
لتحديد العنوان الذي سيتم وضع القيمة فيه. إذا قبلنا أن الإحداثيات الحالية هي X: Y ، بالنسبة لهم SI-1 ، إذن:
mov [si-2], al
- سجل لونًا جديدًا عند النقطة X-1: Y ، على يسار اللون الحالي. يتم طرح 2 من SI بسبب السبب الموصوف أعلاه ، حيث تم بالفعل إضافة وحدة إضافية إليهاmov [si], al
- سجل لونًا جديدًا عند النقطة X + 1: Y ، إلى يمين اللون الحالي. لدى SI بالفعل X + 1mov [bx+si-1], al
- كتابة لون جديد إلى النقطة X: Y + 1 ، أسفل اللون الحالي. مرة أخرى استخدم BX لـ Y + 1mov [si-1-1*320], al
- كتابة لون جديد إلى النقطة X: Y-1 ، أعلى اللون الحالي. لن نتمكن من استخدام BX ، نظرًا لأننا بحاجة إلى إزالة الإحداثيات ، فإن بنية المعالج لا تسمح لنا بالقيام بذلك في هذا النموذج ، وبالتالي يتم استخدام ثابت وفقًا لصيغة الحد من الإحداثيات
سجل القطاع هو DS ، والذي يستخدم بشكل افتراضي مع SI و BX.
لا يتم فحص الموقف في أي مكان عندما تصل النقطة إلى حافة الشاشة. لا يمكن أن يؤدي هذا إلى الفشل ، لأننا سنكون دائمًا ضمن حدود مقطع الفيديو. يمكن أن تقع نقطة مجاورة إما في منطقة غير مبلَّغ عنها بعناوين أكثر من 64000 أو على خط مجاور ، مما لا يضرنا بل ويساعد قليلاً ، كما سيتضح من الوصف الإضافي.
السحر نفسه ، حساب إحداثيات النقطة التالية NEXT_PIXEL: add si, dx ;03 f2 inc dx ;42 jnz FLAME ;75 e3(-29)
دعنا نعود قليلاً ، لم نقم بتعيين قيمة SI الأولية على وجه التحديد في أي مكان ، وفي DX لا يزال لدينا عدد منفذ إدخال الإخراج الذي استخدمناه للوحة. نقوم بتنفيذ ثلاثة إجراءات بسيطة فقط SI = SI + DX ، ومن الواضح أن هذا سيحدد إحداثيات جديدة ، أي منها؟ DX = DX + 1 وإذا كانت DX لا تساوي 0 ، ثم عد إلى الخوارزمية الأساسية للحصول على النقاط المجاورة وحسابها ، هل DX نوع من العداد؟
نحن نعلم أننا بحاجة إلى الالتفاف على جميع النقاط وحساب التغييرات سطوع جيرانهم. إذا قمت بذلك على التوالي ، فمن المحتمل أن نحصل على تدرج ثابت ، ربما ليس بشكل متساوٍ ، لكن بدون تغيير حول خطوطنا.
نحن نعلم حجم شاشتنا وعدد النقاط التي نحتاج إلى الالتفاف عليها ، ولكننا هنا نتجاهلها بشكل أدق ، على وجه التحديد ، نختار القيمة القريبة 65536 بدلاً من 64000 بالضبط. DX هو حقًا عداد ، 65536 فقط. ولكن لماذا لا تكون قيمته الأولية مهمة ولماذا نتخذها هل القيمة النهائية أكبر من إجمالي النقاط على الشاشة؟لأننا نلتف حول النقاط ليس على التوالي وليس كل شيء. كل إحداثي خطي لاحق أكبر من الإحداثي السابق بقيمة DX. هذا هو ، في SI مجموع عناصر DX للتقدم الحسابي البسيط: 0،1،2،3،4،5،6، ...، 362،363، ...، 65535. هذا يعطينا بالفعل non-linearity ، إذا بدأت بـ SI = 0 و DX = 0 ، ثم في SI نحصل على: 0،1،3،4،6،10،15،21، ...، 65341،65703، ...، 2147450880.ولكن هذا ليس كل شيء ، نظرًا لأن البعد SI هو 16 بت ، لا يمكننا الحصول على قيمة أكبر من 65535 ، يحدث تجاوز السعة ويبقى الباقي في SI modulo 65536. تأخذ صيغة حساب الإحداثيات الخطية النموذج SI = (SI + DX) MOD 65536 ، الذي يكسر تمامًا الترتيب المستمر: 0،1،3،4،6،10،15،21، ...، 65341،167،530،894، ...الآن نتذكر أن SI لم تتم تهيئته بأي شكل من الأشكال ، وهذا هو ، في المرة القادمة نعود إلى هذه الدورة بعد ذلك سنبدأ من الإحداثيات التي توقفنا فيها ، وليس من 0 أو بعضها معطى. سيؤدي ذلك إلى إضافة فوضى إلى تسلسلنا - إطالة عدد العناصر غير المتكررة. خلاف ذلك ، سيكون اجتياز النقاط دائمًا كما هو ، وإن لم يكن خطيًا. سيكون لهب تأثير ، ولكن ليس بشكل واضح. إذا كنا نتحدث عن الخدعة ، فهذه هي الحقيقة.DX ، دائمًا ، باستثناء الاستخدام الأول ، يبدأ ضمنيًا عند 0 نتيجة لتجاوز سعة inc dx
.ويتم إضافة المزيد من الفوضى من خلال قيمنا الحدودية ، لأنه في حالة SI> = 64000 لن يتم رسم نقاط وسيتم خلط تسلسل الإخراج قليلاً. وتخطي جميع النقاط بقيمة الصفر يؤدي إلى تأثير الاشتعال في الثواني القليلة الأولى من البرنامج. هذا لأن الدورة الكاملة تنتهي بشكل أسرع ، حيث أن معظم النقاط لا تتم معالجتها. ولكن الأهم من ذلك ، نظرًا لأن السطوع لمعظم النقاط سيزداد فقط ، لا يمكن حجبها بواسطة أقسام باهتة مجاورة - فهي ببساطة غير موجودة حتى الآن ، ولا يتم احتساب قيم الصفر. بعد اختفاء المناطق السوداء تمامًا ، يتم إنشاء توازن ، وستزيد بعض المناطق من السطوع ، بينما ستنخفض بعض المناطق.نتيجةً لذلك ، لا يمكننا التحدث عن أي ترتيب أو تدرج لوني بعد الآن ، يتم تجاوز النقاط ، في كل مرة في تسلسل جديد ، بما في ذلك التكرار عدة مرات أو تخطي كليًا. يؤدي ذلك إلى تكوين مناطق ذات سطوع مختلف مخلوطة مع بعضها البعض ، وتتغير في كل تكرار جديد.ولكن هذا ليس كل شيء ، إذا لم تقم بإضافة نقاط مضيئة جديدة ، فسيتم سدادها جميعًا في النهاية. لذلك ، بعد أن يصل DX إلى أقصى قيمة له ، نعود إلى رسم خمسة خطوط ساطعة مرة أخرى ونعيد حساب جميع النقاط التي تظهر على الشاشة: in al, 60h ;e4 60 cmp al, 01h ;3c 01 jne LINES ;75 a5(-91)
لكن قبل ذلك ، نقرأ من المنفذ 60 ساعة ، هذه هي لوحة المفاتيح ، رمز مسح آخر مفتاح مضغوط. بالنسبة إلى ESC ، فهي تساوي 1. إذا كان الأمر كذلك ، فقد تم الضغط على مفتاح ESC ، ونحن نتحرك صوب الخروج.اكتمال
تجدر الإشارة إلى أنه أثناء تحديث الشاشة الحالية ، والتي تستغرق بعض الوقت ، لا يمكنك الخروج من البرنامج ، أي أن رد الفعل على ESC سيتأخر. إذا تم الضغط على بعض المفاتيح أثناء الانتظار وبعد ESC ، سنظل في البرنامج ، يمكن قراءة رمز المسح الأخير فقط من المنفذ. شيء آخر ، نحن لا نستبدل أو نستخدم وظائف نظام DOS و BIOS لهذا ، بصرف النظر عن ما نقرأه من المنفذ ، يتم وضع المفتاح المضغوط في مخزن مؤقت دائري ومن المحتمل أن تتم قراءته من هناك بواسطة البرنامج التالي بعد اكتمال مقدمة البرنامج ، على الأرجح ملف مدير أو command.com
. سيؤدي ذلك إلى معالجتها ، على سبيل المثال ، سوف يخفي Volkov Commander في ESC لوحاته.يبقى العودة إلى وضع النص 3: mov ax, 03h ;b8 03 00 int 10h ;cd 10
من المفترض أننا كنا في هذا الوضع قبل إطلاق البرنامج ، ولكن في الحالة العامة قد لا يكون هذا هو الحال. هنا نقوم بتحديث AX بالكامل ، لأننا نعرف على وجه اليقين أن AH لا يحتوي على 0.يمكنك الآن الخروج: retn ;c3
هذا أمر قريب من الإجراء الذي يأخذ قيمة الكلمة الموضوعة هناك (وحدتي بايت) من المكدس ويقوم بتحميلها في عداد أوامر IP. وفقًا للشروط الأولية ، لدينا أصفار في المكدس ، وهذا سيؤدي بنا إلى عنوان CS: 0 ، حيث نعلم أنه يوجد رمز الأمر int 20h
- إيقاف التشغيل.و 7 بايت لحقوق النشر: dd 0h ;00 00 00 00 db 'Mcm' ;4d 63 6d end
يمكننا القول أنه لا يزال هناك مكان أقضي فيه على تهيئة أكثر صرامة ، ولكن بما أن كل شيء يعمل في DOSBox الحديث ، فربما يكون المؤلف قد فعل كل شيء بشكل صحيح.دعنا نذهب مرة أخرى:- ,
- 4 , : X+1 Y+2, X+2 Y+1. , . ,
- SI=(SI+DX) MOD 65536, DX , , , SI. 1. 65536 , , . , —
add si, dx
inc dx
, , - ESC ,
. .186 .model tiny .code .startup mov al, 13h int 10h push 0a000h pop es push es pop ds lodsb mov dx, 03c8h out dx, al inc dx mov cl, 040h PALETTE: out dx, al inc ax outsb outsb loop PALETTE LINES: mov ax, 03f3fh mov bx, 0+1*320 mov di, 64+4*320 push di mov cl, 120 LINE1: stosw add di, bx loop LINE1 pop di mov cl, 96 LINE2: mov [bx+di], al stosb add di, bx add di, bx loop LINE2 mov cl, 97 LINE3: mov [bx+di], al stosb sub di, bx sub di, bx loop LINE3 mov di, 17+123*320 push di mov cl, 120 LINE4: stosw sub di, bx loop LINE4 pop di mov cl, 143 rep stosw FLAME: cmp si, 320*200 jae NEXT_PIXEL lodsb or al,al jz NEXT_PIXEL dec ax mov [si-2], al mov [si], al mov [bx+si-1], al mov [si-1-1*320], al NEXT_PIXEL: add si, dx inc dx jnz FLAME in al, 60h cmp al, 01h jne LINES mov ax, 03h int 10h retn dd 0h db 'Mcm' end
لتجميع ، يجب عليك القيام به: tasm pentagra.asm
و tlink /t pentagra.obj
.لا أعرف ما إذا كان من الواضح لك ما الذي تم تنفيذه وكيف تم تنفيذه ، لكن يبدو لي أنه تم استخدام أسلوب جميل وغير عادي لإنشاء تأثير اللهب. على الرغم من أنني لا أملك شيئًا لمقارنته به ، فربما فعله الجميع ، والآن يمكنك فعل الشيء نفسه.