صفحات

۱۳۹۴ فروردین ۳۰, یکشنبه

آموزش برنامه نویسی اسمبلی برای کمودور 64، قسمت اول

21 سال از تولید آخرین کمودور 64 می گذرد با این حال این کامپیوتر در بین نسل جدید هواداران فراوانی دارد. هم اینک می توانید ده ها فروم و صدها سایت را که منحصرا به بازیها و برنامه ها و مجلات این کامپیوتر اختصاص داده شده اند، در سطح اینترنت مشاهده کنید. در سالهای اخیر چندین کلون از این کامپیوتر دوست داشتنی ساخته شده. کمودور 64 یکی از بخش های همیشه پرطرفدار مسابقه های ساخت دمو و بازی  است(مانند Assembly demo party).
با استناد به گفته کتاب رکوردهای گینس کمودور64 پرفروش ترین مدل کامپیوتر در طول تاریخ می باشد. ارزیابی های مستقل انجام گرفته، تعداد کامپیوترهای فروش رفته را چیزی بین 10 تا 17 میلیون عدد می دانند.
در اوایل دهه 80، C64 با قیمت کمتر(595$) و سخت افزار قابل انعطاف بیشتر در مقایسه با رقبایی مثل Apple II وAtari 800، به سرعت توانست  در فروش از آنها پیشی بگیرد و به عنوان یک کامپیوتر خانگی و دستگاه بازی خود را در دل خانواده ها و حتی  خوره های کامپیوتر و هکرها(همچون گروه FairLight) جا دهد. با این حال قیمتش به حدی نبود که خانواده من یا Linus Torvalds (خالق هسته لینوکس) از پس تهیه آن بر بیایند، و ما دسته ای دیگر از طرفداران کمودور64 بودیم که حسرت داشتنش فقط نصیب ما شده بود (: (مصاحبه لینوس). من برای رسیدن به آرزوی خود تا اوایل دهه 90 صبرکردم، زمانی که قیمت دیسک درایو 1/4و5 اینچی خارجی آن(کمودور 1541) از خود دستگاه بیشتر بود! و با وجود تقاضا، تولید C64 برای شرکت کمودور صرف نمی کرد(قیمت دستگاه چیزی حدود 50 پوند)

کمودور128 آخرین مدل کامپیوتر 8-بیتی تولید شده از طرف شرکت کمودور، به نوعی گسترش یافته C64 بود که با داشتن دو سی.پی.یو MOS 8502 و Zilog Z80A و سه مد کاری C64 و C128 و CP/M با سلف خود، کمودور64، نزدیک به %100 سازگاری داشت. C128 میتوانست سیستم عامل CP/M را از طریق دیسکت بوت کند برخلاف C64 که سیستم عامل اش داخل ROM بود.
کمودور 65 یا C64DX یک پیش نمونه از طرف شرکت کمودور بود. نسخه بهبود یافته C64، که در حین سازگاری کامل با پیشینیان خود دارای خصیصه های پیشرفته ای هم بود که در کامپیوترهای آمیگا دیده می شد. تعداد انگشت شماری از این کامپیوتر تولید شده.

اجزای سخت افزاری و نرم افزاری تشکیل دهنده C64

MOS Technology 6510 یک ریزپردازنده 8 بیتی که توسط شرکت MOS Technology, Inc طراحی شده بود و یک شکل کمی اصلاح شده از ریزپردازنده بسیار موفق 6502 می باشد. اضافه کردن یک پورت ورودی/خروجی 8 بیتی همه منظوره(در رایج ترین نسخه 6510 تنها 6 پورت ورودی/خروجی در دسترس است) یک تغییر اساسی نسبت به 6502 بود. به علاوه آدرس باس می توانست منطق سه حالته ایجاد کند.
وظیفه این ریزتراشه (که دو نسخه PAL و NTSC آن ساخته شده بود)، تولید پیام های ویدئویی Y/C و پیام های تازه سازی حافظه با دسترسی تصادفی پویا(DRAM) است.
چیپ 6581/8580 که در C64 تعبیه شده، تولید کننده قابل برنامه ریزی صدا است. یکی از اولین چیپ های صدا است که پیش از انقلاب صدای دیجیتال در یک کامپیوترهای خانگی گنجانده شده بود.

مدار مجتمعی که بوسیله MOS Technology ساخته شده بود برای پردازشگرهای خانواده  6502 به عنوان کنترلر درگاه ورودی/خروجی، قابلیت های ورودی/خروجی موازی و سریال را فراهم میکرد. همچنین دارای دو تایمر قابل برنامه ریزی و یک ساعت است،(که زمان و روز را نشان می دهد). در داخل کمودور64، دو عدد از این آی سی وجود دارد.
  • حافظه: 64KB RAM+20KB ROM
16KB از فضای حافظه RAM می تواند مورد استفاده چیپ گرافیک VIC-II قرار گیرد، این حافظه برای ذخیره محتوای صفحه نمایش، کاراکترها و اسپرایت ها قرار می گیرد.
سیستم عامل کمودور64،KERNAL به همراه مفسر بیسیک نسخه 2.0 در داخل ROM جای گرفته است.

  • BASIC
 درست مثل بیشتر کامپیوترهای خانگی اوایل دهه 80، زبان برنامه نویسی بیسک ضمیمه کمودور64 بود و در ROM قرار داشت. سیستم عامل به شکل امروزی نبود. KERNAL با استفاده از دستورات بیسیک در دسترس بود. دیسک درایو کمودور 64  مانند آتاری 800 خودش دارای پردازشگر مستقلی بود، این بدین معنی است که هیچ فضایی از حافظه کمودور64 برای اجرای سیستم عامل دیسک (DOS) اشغال نشده است.
بدیل اینکه شرکت کمودور تصور نمی کرد خیلی ها دیسک درایو بخرند(همراه کمودور64 یک دستگاه اختصاصی نوار مغناطیسی ذخیره داده به نام Commodore 1530 Datasette وجود داشت)، به جای استفاده از بیسیک خیلی پیشرفته نسخه 4.0 که در کامپیوترهای خانواده PET وجود داشت و برای عملیات دیسک بهینه شده بود، از بیسیک نسخه 2.0 استفاده کرد. در نتیجه آن روزها شما برای مدیریت دیسک باید از روشهای تقریبا دشواری استفاده می کردید.



بیسیک نسخه 2.0 محدود شده بود و دستورات ویژه دستکاری صدا و تصویر را در بر نداشت به جای آن کاربران را ملزم می کرد از دستورات PEEK & POKE برای دسترسی مستقیم به ثبات های تراشه استفاده کنند(معمولا برنامه نویسان آدرس این ثبات ها را به خاطر می سپردند تا نیاز به مراجعه همیشگی به کتابچه راهنما نداشته باشند). شرکت کمودور دو ضمیمه مختلف در قالب کارتریج‬‎ تولید کرد که دستورات توسعه یافته(شامل صدا و تصویر) را به بیسیک نسخه 2.0 می افزود:
جالب است بدانید که Simons' BASIC توسط یک پسر 16 ساله بریتانیایی به نام David Simons نوشته شده. او اولین کامپیوترش را سه سال قبل تر(13 سالگی) از پدر هدیه گرفته بود.Simons' BASIC، صدو چهارده دستور مفید را به بیسیک نسخه 2.0 اضافه می کند. نویسنده برنامه، به درخواست کاربران انجمن lemon64، اطلاعات جالب و دست اولی را در مورد ساخت و فروش آن کاتریج پس از سالها ، بیان میکند.
  • Commodore DOS

  •  ابزارهای جانبی

رایج ترین کاتریج های که از آنها به عنوان ابزار توسعه و سرگرمی استفاده می شده، اینها هستند :
 Datel "Action Replay", Evesham Micros "Freeze Frame MK III B", Trilogic "Expert", "The Final Cartridge III", and Super Snapshot


تمامی این کارتریج ها دارای امکانات زیر هستند:
  1. RESET:  بدلیل اینکه کمودور 64 فاقد دکه ریست بود، با استفاده از این دکمه که روی کارتریج قرار داشت می توانستید کمودور64 خود را ریست کنید.
  2. Freezer: کارکرد این دکمه که روی کاتریج قرار داشت، این بود که شما با استفاده از آن می توانستید برنامه های در حال اجرا را متوقف کنید و محتویات حافظه را در دیسکت یا نوار ذخیره کنید یا اینکه محتوای صفحه نمایش را به چاپگر بفرستید و سپس .
  3. Monitor Program(برنامه ناظر): این ویژگی نرم افزاری به ما این اجازه را می داد که بتوانیم کد اسمبلی را مستقیما در مکان دلخواه مان در حافظه قرار دهیم و قسمتی از حافظه را به دیسکت/نوار انتقال دهیم یا از آن بار کنیم و یا محتویات  ثبات ها و حافظه را دستکاری کنیم. این مورد آخری امکان تقلب در بازی ها را به ما می داد، بدین شکل که، فرضا با دانستن آدرسی از حافظه که تعداد جان های ما در آن قرار داشت می توانستیم آن را به حداکثر برسانبم و یا از جانهای دشمنانمان کم کنیم! یا بازی را به مرحله دلخواه مان ببریم.. دهه 60 و اوایل دهه 70 مجلات کامپیوتری در ایران پر بود از این آدرس ها و مقادیری که باید در آن ریخته می شدند (به آن کد نسوز هم می گفتند).
  4. Fast loader: سرعت بار کردن و ذخیره را از/به دیسک و نوار شتاب می بخشند. استفاده از این امکان (که بر پایه نرم افزار است)، سرعت بار کردن را بین 5 تا 15 برابر بیشتر می کند.
     
  • زبانهای برنامه نویسی
 غیر از بیسیک زبانهای دیگری برای کمودور64 موجود است از جمله: Pascal و C و Logo و Forth و Fortran(لیست کلی زبانهای قابل استفاده برای کمودور). نسخه کامپایلری از زبان بیسیک هم تولید شده بود، مانند: Petspeed 2 از شرکت کمودور و Turbo Lightning از Ocean Software. در حالیکه نسل اول برنامه های نوشته شده برای کمودور 64 ممکن است از زبانهای بالا و یا حتی بیسیک استاندارد استفاده کرده باشند، اما از سال 1983 به بعد، غالب برنامه های حرفه ای تولید شده برای کمودور 64 به زبان اسمبلی نوشته شده اند( یا روی یک کامپیوتر بزرگتر با استفاده از یک Cross_compiler نوشته و تولید شده اند و یا مستقیما روی خود کمودور با استفاده از ابزارهای machine code monitor و assembler). به حداکثر رساندن سرعت اجرای برنامه و به حداقل رساندن استفاده از حافظه، دو دلیل عمده بکارگیری زبان اسمبلی در نوشتن برنامه ها است.
نکته: پیشنهاد می کنم به جای نوشتن مستقیم برنامه روی کمودور64، از یک همگردان دوگانه(Cross_compiler) که روی کامپیوتر شخصی تان اجرا می شود، استفاده کنید، با ذکر یک مثال، دلیلش را توضیح می دهم:  
زبان C یک زبان همه منظوره دستوری و ساخت یافته است که میتوان مفاهیم و ساختارهایش را به طور کارآمدی به دستورات ماشین تبدبل کرد. بنابراین برای نوشتن همه نوع برنامه از جمله سیستم عامل که سابقا با زبان ماشین نوشته می شده، قابل استفاده است. کامپایلر آن هم  برای انواع سیستم ها موجود است، از سامانه نهفته(embedded system) گرفته  تا ابررایانه. برای کمودور 64؛ چهار کامپایلر وجود دارد: C Power و Better Working-Power C و Small C Compiler و Super C. همه این کامپایلرها زیرمجموعه محدودی از نسخه K&C زبان C هستند نه نسخه استاندار آن(ANSI C). به همین دلیل برنامه های نوشته شده روی دیگر کامپایلرها، قابلیت انتقال به اینها را ندارند. از طرفی ویرایشگر این کامپایلرها نسبت به نمونه های مشابه امروزی شان بسیار ابتدایی به نظر می رسند و در عمل نیز کارهای مهمی مثل یافتن خطا و غلطگیری و... در آنها مشکل است (به جای اینها می توانید از کامپایلر مدرن CC65  روی کامپیوتر شخصی تان استفاده کنید). از طرفی ساخت یک دمو یا بازی به روزها و شاید ماهها وقت نیاز دارد و استفاده از سیستمی که سالها از عمرش می گذرد، آن هم برای برنامه نویسی اصلا توصیه نمی شود.
در صورتی که به کمودور64 دسترسی ندارید می توانید از برابرساز، VICE برای اجرای برنامه هایتان استفاده کنید. به صفحه رسمی برنامه VICE  در sourceforge.net مراجعه کنید و با توجه به نوع سیستم عامل و معماری پردازشگر دستگاه تان(32 بیت یا 64 بیت ویا ایتانیوم) یکی از لینک ها را انتخاب کرده و آن را دانلود کنید. فایل برنامه را از حالت فشرده خارج کرده و به یک پوشه مشخص انتقال دهید(بعدا به آدرس این پوشه نیاز داریم)
برنامه VICE کلیه کامپیوترهای 8-بیتی شرکت کمودور را که شامل C64 و C128 و VIC-20 وC64 Direct-to-TV و   Plus/4 و همه مدل های PET را (از جمله CBM-II)، تقلید می کند. البته از خصیصه های غیر استاندارد SuperPET 9000 چشم پوشی کرده است.
در این وبلاگ بیشتر به کمودور 64 و 128 می پردازم (چون تجربه کار و برنامه نویسی با این دو کامپیوتر را دارم). برای شبیه سازی کمودور 64 در ویندوز کافیست به پوشه ای که برنامه VICE را در آن ریخته ایم مراجعه کرده و فایل X64.exe را اجرا کنیم. به همین راحتی صاحب یک کمودور 64 می شویم (: .
برای  استفاده از دیسکت و نوار و کارتریج، باید رونوشت هایی (Image) که از این رسانه ها تهیه شده است را به برنامه متصل (Attach) کنیم.
نحوه استفاده از فایل های با پسوند D64 (رونوشت فلاپی دیسک 1541 کمودور) در برنامه VICE:
فایل C64assembly.d64، که رونوشتی از یک دیسکت کمودور 64 است، را دانلود کنید. داخل این دیسکت من دو Machine Code Monitor به نام های Supermon+64(نوشته Jim Butterfield) و MLM64 Plus قرار داده ام. برنامه VICE را اجرا کنید، از منوی فایل File، زیرمنوهای Attach disk Image=>Drive 8 را انتخاب کنید، به پنجره دیالوگی که ظاهر می شود، مسیر و نام فایلی را که دانلود کرده اید، بدهید و سپس دکمه Attach را بزنید.
در ویرایشگر بیسیک با دستور زیر می توانید، لیست فایلهای موجود در دیسکت را بدست آورید:
LOAD "$",8
LIST
 نکته: بعد از پایان هر خط در ویرایشگر بیسیک کلید Return (در امولاتور کلید Enter ) را بزنید
نکته فلاپی دیسک های کمودور 1541 می توانند حاوی حداکثر 144 فایل( در یک فضای مسطح و بدون زیر دایرکتوری)، باشند. دایرکتوری در track رزرو 18ام یعنی درست در شیار وسطی یک دیسکت 35 شیارۀ تک لبه، ذخیره می شود.
نکته: اگر از قبل برنامه ای به زبان بیسیک نوشته اید بهتر است با دستور SAVE "filename",8 آن را در دیسکت ذخیره کنید در غیر اینصورا برنامه بیسیک تان را از دست خواهید داد، چون سیستم عامل لیست فایل های موجود در دیسکت را درست جایی از حافظه که برنامه بیسک در آن وجود دارد، قرار می دهد. برای رفع این مشکل می توانید از دستورات ویژه ای که کاتریج های Epyx FastLoad و Action Replay و The Final Cartridge III ضمیمه بیسیک 2.0 می کنند، استفاده کنید. این دستورات  بدون اینکه برنامه بیسک موجود در حافظه را تخریب کنند، اجازه می دهند که directory دیسکت در حافظه نمایش بار شود (بیسیک نسخه 7.0 در کمودور 128 شامل دستورات DIRECTORY و CATALOG است که همین وظیفه را انجام می دهند).
پس از مشاهده دایرکتوری می توانیم، با دستور LOAD "filename",8,1 برنامه ای را در مکان مشخص در حافظه  بار می کنیم و با دستور RUN آن را اجرا می کنیم.
مثال:
LOAD "supermon+64",8,1
RUN
با وارد کردن این دستورات برنامه مانیتور supermon+64 اجرا خواهد شد. برای خروج از برنامه کلید X و سپس Return را می زنیم.

نکته: بایت اول و دوم یک فایل از نوع PRG، نشان دهنده یک آدرس 16 بیتی به شکل Little-endian است(بایت کم ارزش در ابتدا و بایت پرارزش در ادامه). این جفت بایت محل بار شدن برنامه در حافظه  را نشان می دهد. وقتی در ویرایشگر بیسیک با دستور SAVE برنامه مان را ذخیره می کنیم، مقدار بایت اول و دوم در فایل مورد اشاره، اعداد به ترتیب 01$ و 08$ می باشد. این دو بایت آدرس 0801$ یعنی محل بار شدن برنامه بیسیک در حافظه را نشان می دهند.
دستور LOAD "filename",8,0 یا LOAD "filename",8 برنامه را در مکان ابتدای حافظۀ بیسیک 0801$(2049) بار می کند اما دستور LOAD "filename",8,1 فایل را در آدرس مشخص شده(بایت اول و دوم فایل باینری) بار می کند. برنامه های زبان ماشین که توسط اسمبلر یا مانیتور تولید شده اند را باید با این دستور در حافظه بار کرد.
نکته: با وارد کردن دستور LOAD "*",8,1، سیستم عامل اولین فایل از نوع PRG (بیسیک یا زبان ماشین) را که در فلاپی دیسک پیدا کند، به حافظه انتقال می دهد.
نکته: در کمودور 64 وارد کردن دستور LOAD "$",8,1 موجب سرازیر شدن سیلی از آشغال به صفحه نمایش می شود به جای اینکه، دایرکتوری را به حافظه بیسیک بفرستد. این بدین خاطر است که دیسک درایو آدرس 0401$(1025) را برای بار کردن دایرکتوری در حافظه تعیین می کند که معادل شروع بیسیک در کامپیوترهای PET است اما در کمودور 64 مطابق با حافظه پیش فرض صفحه نمایش است(آدرس کاراکتر دوم بر روی خط اول صفحه نمایش).

  • Assembler: اسمبلر زبانی است که دستورات رمزماشین محلی CPU را در یک شکل "قابل خواندن توسط انسان"، ارائه می دهد. این زبان به اسمبلی یا اسمبلر معروف است، و برنامه کامپایلری که دستورات "قابل خواندن توسط انسان" را به یک فایل برنامۀ قابل اجرا ترجمه می کند، اسمبلر نامیده می شود. کامپایل کردن متن مبدأ(source code) به یک زبان ماشین قابل اجرا "اسمبلی" نامیده می شود. معکوس این رویه (تبدیل کد ماشین به یک کد کم و بیش قابل خواندن)  را "disassembly" می نامند.
معماری هر پردازشگری(به طور مثال x86وMIPSو6502و68000) مجموعه دستورات و نحو(syntax) مال خودش را دارد، بنابراین یک زبان اسمبلی متفاوت. بیشتر زبان های اسمبلی شباهت هایی را نشان می دهند اما هنوز هم تنها منحصر به یک معماری CPU خاص هستند. به همین دلیل مردم صحبت از "زبان اسمبلی 6502" یا "اسمبلر 68000" می کنند تا رفع ابهام کرده باشند. دستورات ماشین به وسیله اعدادی نمایندگی می شود که به شکل کد باینری در حافظه کامپیوتر ذخیره شده اند.
کدهای برنامه در زبان ماشین یک لیست از ساختارهای بیتی(صفر و یک) است که از دو قسمت کد دستورات(Opcodes) و عملوندها(operands) تشکیل شده.
در علم کامپیوتر Opcode به قسمتی از دستور زبان ماشین گفته می شود که عمل مورد اجرا توسط سی.پی.یو را مشخص می کند. معمولا دستورات زبان ماشین علاوه بر Opcode داده هایی را هم جهت پردازش مشخص می کنند که به آنها operands یا عملوند(ها) می گوییم.
Mnemonic: همانطوری که به نظر می رسد، به یاد آوردن ساختارهای بیتی برای همه دستورات کار بسیار مشکلی است. زبان اسمبلر، میانبرهایی به نام یادافزا(mnemonic) را که به یاد آوردن آن ها بسیار آسان است به کار می برد. یک اسمبلر(کامپایلر) این یادافزاها را به متناظرشان(Opcode و Data) ترجمه می کند.
برای مثال:
*=$033c                                                        
lda #$06                               ;بار کن عدد 6 را در ثبات انباره
sta $d020                             ;ذخیره کن محتوای ثبات انباره را در ثبات مربوط به رنگ حاشیه
...
داخل RAM کمودور 64 به این شکل ارائه داده می شود:
Address            Opcode+Operand(s)
033c                 A9 06                     ;"033c"=Memory Address, "A9"=Opcode, "06"=Operand
033e                 8D 20 D0               ;"033e"=Memory Address, "8D"=Opcode, "20","D0"=Operand
...
و به شکل کد باینری از آدرس 033c$
 1010100100000110100011010010000011010000

  • pseudo-opcode یا assembler directive: به دستوراتی گفته می شود که اسمبلر را در انجام عملیات(به غیر از اسمبل کردن) راهنمایی می کنند.
  • Cross Assembler به ما این امکان را می دهد که برنامه های اسمبلی را در محیط دلخواه خود بنویسیم و نتیجه را که برنامه ای به زبان ماشین است، به کمودور 64 یا امولاتور انتقال دهیم. به عقیده من ساخت برنامه در ادیتورهای ویندوز بسیار راحت تر از ویرایشگرهای کمودور 64 است.
کراس اسمبلرهای تحت ویندوز فراوانی برای کمودور 64 وجود دارند مانند: DASM و ACME و CCC65 Assembler و... .اما رابط کاربری بیشتر آنها مبتنی بر خط فرمان است نه گرافیک. C64Studio یک محیط یکپارچۀ ساخت و تولید بازی برای کمودور و آتاری است که شامل ابزارهای،AssemblerوDisAssemblerوDebugو ویراشگرهای کاراکتر، اسپرایت و نقشه می شود.
  • نصب و راه اندازی C64Studio
 برنامه C64Studio را ازسایت سازنده اش دانلود کرده و سپس آن را از حالت فشرده خارج کنید. برای اجرای برنامه نیاز به داشتن آخرین نسخه چارچوب دات نت(NET Framework.) دارید، که می توانید آنرا از سایت مایکروسافت دانلود کنید.
به پوشه برنامه رفته و فایل C64Studio.exe را اجرا کنید، قبل از نوشتن برنامه اسمبلی استفاده باید تنظیمی در برنامه انجام دهیم.
منوی File و سپس زیرمنوی Setup Wizard را کلیک کنید. با کیک روی دکمه (...) پنجرۀ دیگری باز می شود که در آن مسیر امولاتور VICE (برای کمودور 64 فایل x64.exe ) را به برنامه می دهیم. بعد از انتخاب فایل و زدن کلید Open دوباره به پنجره قبل باز می گردیم، در آخر دکمه OK را می زنیم.

حال آماده ایم که اولین برنامه مان را به زبان اسمبلی بنویسیم، منوهای File=>New=>Solution را انتخاب کنید. برای راهکارتان یک نام و یک پوشه برای ذخیره شدن برگزینید. از منوی Solution، زیرمنوی Save را انتخاب کنید. از منوی File، زیرمنوهای New=>Project را انتخاب کنید. یک نام  یک پوشه برای ذخیره پروژه تان برگزینید(هر راهکاری می تواند شامل چندین پروژه مجزا باشد). از منوی Project زیرمنوی Save را بزنید. حالا به پروژه مان یک فایل اسمبلی اضافه می کنیم، منوهای File=>New=>ASM File را به ترتیب انتخاب کنید، از جعبه پیام ظاهر شده دکمه Yes را انتخاب کنید تا فایل اسمبلی به پروژه مان اضافه شود. سپس در پنجره ظاهر شده یک نام و مسیر برای ذخیره فایل اسمبلی تان برگزینید و در پایان دکمه Open را بزنید. از منوی Project زیرمنوی Save را بزنید.
به عنوان شروع بیایید با هم نگاهی بیاندازیم به یک برنامه ساده که هدفش تغییر دادن رنگ زمینۀ صفحه نمایش و حاشیه است.

اگر به خروجی تصویر کمودور 64 در تلویزیون یا مانتیتور دقت کنید می بینید که صفحه نمایش پیش فرض کمودور 64 به دو قسمت آبی تیره و روشن تقسیم شده است.

پنجره داخلی را Screen و آن بیرونی را حاشیه یا Border می گویند. کاربر به جز عوض کردن رنگ زمینه یا Background قدرت دستکاری دیگری را در قسمت Border ندارد. تنها با استفاده از تکنیک وقفه Raster می توانیم روی حاشیه اعمالی را انجام دهیم.کمودور 64 از چیپ گرافیک VIC-II برای تولید سیگنال های تصویری بهره می برد. این چیپ دارای آدرس باس 14 بیتی است که می تواند یکی از چهار قطعۀ 16 کیلو بایتی فضای حافظه کمودور 64 را برای داده های ویدئویی مورد استفاده قرار دهد. همچنین قدرت تفکیک تصویر حداکثر 200*320 پیکسل(200*160 در حالت چند رنگ) را داراست. از یک پالت رنگ 16 تایی ثابت استفاده می کند. داری 47 ثبات خواندنی/نوشتی است که با دستورات بیسیک یا ماشین به سهولت می توان به آنها دسترسی داشت. در پست های آتی جزئیات مفصلی در مورد چیپ VIC-II و نحوه استفاده از آن خواهم گفت.

لیست برنامه:
;change border & screen color
!to "main.prg",cbm
*=$033c
lda #$03
sta $d020; border color=3
lda #$02
sta $d021; screen color=2
rts
شرح برنامه:
 ;change border & screen color
در این اسمبلر توضیحات با پیشوند ; بیان می گردند. در برخی اسمبرها استفاده از علامات // و /* */ برای دادن توضیح مجاز است.
!to "main.prg",cbm
to! یک راهنمای اسمبلر است. به کمک این دستور می توانیم نام فایل خروجی و نوع آن را تعیین کنیم. در این مثال چون نوع فایل خروجی را CBM تعیین کرده ایم، یک آدرس دو بایتی low endian، که مکان بار شدن برنامه در حافظه را نشان می دهد، به ابتدای فایل ضمیمه خواهد شد.
*=$033c
 با استفاده از راهنمای اسمبلر =*، مکان بار شدن برنامه در حافظه را مشخص می کنیم. در این مثال 033c$ (آدرس شروع بافر نوارخوان کمودور 64) را انتخاب کرده ایم.
هشدار: در صورت استفاده از نوارخوان، برای  ذخیره و بازیابی اطلاعات، محتویات بافر تغییر خواهد کرد و در نتیجه برنامه نابود خواهد شد. بافر نوارخوان در محدوده آدرس 033C$ تا 03FB$ قرار دارد(192 بایت). تنها برای آزمایش برنامه های کوچک ، می توانیم از این آدرس استفاده کنیم.
نکته: کامپایلرهای KickAssembler و DASM، به ترتیب PC. و org را به جای حکم =* بکار می برند.

عدد 3 در رجیستر انباره (A) بار شود.
نکته: علامت $ به معنای استفاده ازعدد در مبنای 16 است.
برای اعداد در واحد دو از علامت % استفاده می کنیم، مانند:
 lda #000011
و اگر عدد پیشوند نداشت، به معنای استفاده از مبنای طبیعی(10) است.
نکته: علامت هشتک(#) در متن دستور به معنای استفاده از آدرس دهی فوری است یعنی اینکه عدد داده شده مستقیما در اجرای دستور بکار می رود. در صورتیکه اگر از علامت هشتک استفاده نکنیم(lda $03) مد آدرس دهی دستور، صفحه صفر خواهد بود، که بدین شکل اجرا می گردد: محتوای خانه سوم حافظه (که در صفحه صفر قرار دارد)، در رجیستر A، بار شود. انواع روش های آدرسی دهی را در این لینک با مثال شرح داده ام.
sta $d020
محتوای رجیستر A (عدد 3) را در حافظه به آدرس 53280(d020 $) ذخیره می کند. این مکان حافظه متعلق به یکی از رجیسترهای تراشه VIC-II است که مقدار رنگ حاشیه در آن نگهداری می شود. رنگ حاشیه می تواند یک عدد بین 0 تا 15 باشد.با اجرای این دستور حاشیه به رنگ یشمی در می آید.
lda #$02
عدد 3 در رجیستر انباره (A) بار شود.

sta $d021
محتوای رجیستر A (عدد 3) را در حافظه به آدرس 53281(d021 $) ذخیره می کند. این مکان حافظه متعلق به یکی از رجیسترهای تراشه VIC-II است که مقدار رنگ زمینه صفحه نمایش(پنجره وسطی) در آن نگه داشته می شود. رنگ زمینه صفحه نمایش می تواند یک عدد بین 0 تا 15 باشد.با اجرای این دستورصفحه نمایش به رنگ قرمز در می آید.

rts

این دستور به معنای بازگشت از زیرروال(Subroutine) است. زیر روال ها با دستور jsr فراخوانی می شوند. زمانی که واحد کنترل پردازشگر حین واکشی(Fetch) دستورات از حافظه به دستور jsr رسید، اول به رجیستر شمارنده برنامه(Program Counter) دو واحد اضافه می کند و نتیجه(آدرس دستور بعد از jsr منهای 1) را به داخل stack، وارد می کند(push)(اول بایت پر ارزش، بعد بایت کم ارزش). سپس کنترل برنامه به زیر روال منتقل می شود. پس از اینکه زیرروال کار خود را انجام داد در پایان از دستور rts برای بازگشت به برنامه اصلی استفاده می کنیم. وقتی که پردازشگر به این دستور رسید یک آدرس دو بایتی را از بالای پشته بیرون می کشد(pull)(اول بایت کم ارزش)، بعد یک واحد به این آدرس اضافه می کند. درحقیقت کنترل برنامه به آدرس دستور بعد از jsr(فراخواننده زیرروال) منتقل می شود. غیر از زیرروال هایی که خودمان می نویسیم، همچنین می توانیم از زیرروال های KERNAL(سیستم عامل کمودور 64 در داخل ROM)، که در مواردی بسیار مفید هستند استفاده کنیم.
Program Counter: ثباتی 16 بیتی در پردازشگر است که آدرس حافظه دستور فعلی در حال اجرا را در خود دارد. تعدادی دستور چه به طور مستقیم یا غیر مستقیم شمارنده برنامه را دستکاری می کنند. انشعاب(branching)، پرش(jumping) و کارکرد وقفه(interrupt) با تغییر شمارنده برنامه در CPU ممکن می شود.

پس از وارد کردن برنامه در ویرایشگر C64Studio از منوی File گزینه Save را انتخاب کنید، سپس برای اجرای برنامه، دکمه Build & Run را که روی میله ابزار است، کلیک کنید. اگر همۀ کارها را به درستی انجام داده باشید اسمبلر بعد از کامپایل کردن برنامه و تولید فایل اجرایی(PRG) آن را تحویل امولاتور VICE می دهد. در صورتی که اسمبلر در هنگام کامپایل کردن برنامه با خطایی مواجه شود، در پنجره Output، تب Compiler Messages نوع خطا و مکان(Line) آن را به اطلاع ما خواهد رساند.

امولاتور VICE به طور اتوماتیک دو دستور بیسیک LOAD و RUN را اجرا می کند. همانطوری که پیش تر گفتم دستور LOAD از سیستم عامل می خواهد که برنامه بیسیک یا ماشین مشخص شده را، در حافظه RAM به آدرسی که به ابتدای فایل اصلی ضمیمه شده، بار کند.(با یک HEX Editor می توانید این آدرس دو بایتی(لیتل اندیان) را مشاهده کنید). دستور RUN فقط در مورد برنامه هایی که به زبان بیسیک نوشته شده اند کاربرد دارد و در مورد برنامه های زبان ماشین باید از دستور SYS استفاده کنیم.
در محیط بیسیک به کمک  دستور SYS به سادگی می توان برنامه زبان ماشین را که در جای مشخصی از حافظه قرار دارد اجرا کرد، برای بازگشت به محیط بیسیک آخرین خط برنامه باید دستور RTS باشد. آدرس شروع این برنامه در حافظه، 033c$ یا 828 است، پس با وارد کردن دستور SYS 828 می توانیم برنامه را اجرا کنیم.
نکته: دستور SYS، قبل از فراخوانی برنامه(با آدرس مشخص شده)، ثبات انباره(A)، ثبات های اندیس X و Y و ثبات وضعیت(SR) را با مقادیری که در آدرس 780–783/$030C–030F وجود دارد، پر می کند، پس از پایان برنامه و تحویل کنترل به بیسیک، دستور SYS فورا محتویات ثبات های گفته شده را در آدرس 780–783 قرار می دهد، که این مقادیر می تواند در آینده مورد استفاده قرار گیرد.
نکته:
در بیسیک با توابع PEEK و POKE، می توانید محتویات هر آدرسی از حافظه را (در محدوده 0 تا 65535) به ترتیب مشاهده و تغییر دهید.
مثال:
POKE 53280,0
این دستور رنگ حاشیه تصویر را به مشکی تغییر می دهد.
POKE 53281, PEEK(53280)
با اجرای این دستور زمینه صفحه نمایش به رنگ حاشیه می شود.


  • Microprocessor Registers
در داخل هر چیپ 650X چندین مکان ذخیره وجود دارد که به آنها register یا ثبات می گوییم. با وجود اینکه ثبات ها اطلاعات را در خود نگهداری می کنند اما اینها را نمی توان به عنوان حافظه(memory) به حساب آورد، چون دارای آدرس نیستند. شش تا از این ثبات ها برای ما خیلی مهم هستند که به طور خلاصه به آن می پردازم:
PC: شمارنده برنامه(program counter) یک رجیستر 16 بیتی است که آدرس حافظه دستور فعلی در حال اجرا را در خود دارد. همان وقت که دستور و عملوند از حافظه واکشی می شود، به مقدار شمارنده برنامه هم افزوده می شود تا نشان دهنده دستور بعدی باشد. تعدادی دستور چه به طور مستقیم یا غیر مستقیم شمارنده برنامه را دستکاری می کنند. انشعاب(branching)، پرش(jumping) و کارکرد وقفه(interrupt) با تغییر شمارنده برنامه در CPU ممکن می شود.
A: انباره(accumulator) یک ثبات 8 بیتی است که اساسا برای عملیات حسابی و منطقی به خدمت گرفته می شود.
X: اندیس(index) یک ثبات 8 بیتی است که عمدتا به عنوان اندیس در بعضی مدهای آدرسی دهی بکار می رود.
Y: اندیس(index) یک ثبات 8 بیتی است که عمدتا به عنوان اندیس در بعضی مدهای آدرسی دهی بکار می رود. همچنین در محاسبات ممیز-شناور به همراه ثبات A می تواند نشان دهنده یک آدرس در حافظه (A/Y) یا یک عدد صحیح علامت دار 16 بیتی(A/Y) باشد.
نکته: از رجیسترهای A و X و Y، می توان برای نگهداری داده استفاده کرد.
SR: ثبات وضعیت پردازشگر(Processor Status Register) یک رجیستر 8 بیتی است که حالت پردازشگر مرکزی را در نتیجۀ عملیات حسابی و منطقی و دستورات ضبط می کند. هدف این رجیستر نگهداری اطلاعات درباره تازه ترین عملیات محاسبه و منطق(ALU) است که انجام گرفته، همچنین کنترل کردن حالت فعال و غیرفعال وقفه ها و تنظیم کردن شیوه عملکرد پردازشگر از وظایف دیگر این ثبات است. حالت پردازشگر مرکزی در هفت پرچم(flag) پردازشگر و کنترل ذخیره می گردد(همگی در یک بایت). هر پرچم مطابق با یک بیت تکی از ثبات حالت پردازشگر است که به طور صریح یا ضمنی قابل خواندن/نوشتن هستند. پرچم ها دو حالت نگاشته(set) و پاک شده(cleared) دارند که در موقع نوشتن باید به ترتیب یک (true) و صفر(false) در بیت ها قرار دهیم. پرچم های N,V,Z,C توسط دستورات انشعاب(branch) قابل خواندن و آزمایش هستند.
7   6   5   4   3   2   1   0    <=BIT
N  V  -   B   D   I   Z   C   <=FLAG
در نوشته های بعد در مورد پرچم ها و کاربردشان بیشتر صحبت خواهم کرد.
SP: اشاره گر پشته(Stack Pointer) یک ثبات داده هشت بیتی در پردازشگرهای 65XX است که به مکان در دسترس بعدی روی پشته اشاره می کند.
در کمودور 64، stack یا پشته یک قطعه ثابت 256 بایتی(یک page) از حافظه است که در آدرس (0100$ تا 01FF$)، رم قرار دارد. پشته یک ساختمان داده LIFO (آخرین ورودی، اولین خروجی) است که مستقیما توسط پردازشگر 6502/6510 برای ذخیره و بازیابی کلمات پردازشگر(بایت ها) بکار گرفته می شود. این ناحیه  از حافظه با رجیستر 8 بیتی SP(اشاره گر پشته) به طور همکار عمل می کنند. اشاره گر پشته همیشه به مکان در دسترس بعدی روی پشته اشاره می کند. مانند بیشتر کامپیوترهای امروزی در کمودور 64، پشته رو به پایین رشد می کند. این بدین معناست که اولین ورودی پشته در آدرس 01FF$ و آخرین ورودی در 0100$ قرار می گیرد. دو کار روی پشته کمودور 64 قابل انجام است، آنها وارد کردن(push) و بیرون کشیدن(pop یا pull) هستند. وقتی یک کلمه/بایت به داخل پشته وارد می شود(push) یعنی مقدارش در مکان حافظه به آدرس SP + $0100 ذخیره شده و از SP کاسته می شود. وقتی که یک مقدار از پشته بیرون کشیده می شود(pop) یعنی به SP افزوده شده و محتوای خانه حافظه به آدرس SP + $0100، خوانده یا بازیابی می شود.
کمودور 64 در چندین عمل و وضعیت، از پشته و اشاره گر پشته استفاده می کند. اصلی ترین استفاده از پشته برای ذخیره(push) "آدرس برگشت" است. زمان بازگشت از یک زیر روال یا رسیدگی کننده وقفه این آدرس مورد استفاده(pop) قرار می گیرد.
 به طور مثال زمانی که یک پیام وقفه دریافت می شود، پردازشگر دستورالعمل فعلی را به طور کامل اجرا می کند، سپس دو چیز را وارد(push) پشته می کند: اول، پردازشگر آدرس دستورالعمل بعدی را وارد پشته می کند(اول بایت پر ارزش بعد کم ارزش). دوم، پردازشگر محتوای ثبات وضعیت را در داخل پشته می ریزد. سرانجام، پردازشگر با توجه به نوع وقفه، یک پرش غیر مستقیم(indirect JMP) با استفاده از یکی از این سه بردار(vector) (که در 6 بایت انتهایی KERNAL ROM، ذخیره شده اند)،  انجام می دهد.
* بردارهای وقفه
$FFFA,$FFFB   <====NMI
$FFFC–$FFFD <===RESET
$FFFE–$FFFF  <===IRQ/BRK
رسیدگی کننده وقفه، پس از به پایان بردن کار، دستور RTI را اجرا می کند. RTI مقدار بالای پشته را برداشته(pop) و در داخل ثبات وضعیت می ریزد، سپس دو بایت بالایی پشته را برداشته(pop) و در داخل ثبات شمارنده برنامه می ریزد.(درحقیقت اجرای برنامه را به آدرسی که از پشته برداشته برمی گرداند).
زمانی که یک زیرروال توسط دستور JSR فراخوانی می شود، پردازشگر از مقدار آدرس دستور العمل بعدی یکی کم می کند و نتیجه را در پشته قرار می دهد(push)(اول بایت پرارزش بعد کم ارزش)، سپس مقدار ثبات وضعیت را به داخل پشته می ریزد(push)، سرانجام کنترل برنامه به زیر روال منتقل می شود. در پایان زیرروال، دستور RTS را قرار می دهیم. دستور RTS مقدار بالای پشته را برداشته(pop) و در داخل ثبات وضعیت می ریزد، سپس دو بایت بالایی پشته را برداشته(pop) و به مقدار آن یکی افزوده و نتیجه را در داخل ثبات شمارنده برنامه می ریزد. در حقیقت اجرای برنامه به آدرس دستور بعد از jsr(فراخواننده زیرروال) منتقل می شود.
دستور PHA مقدار ثبات انباره را وارد پشته می کند(push) و PLA مقدار بالای پشته را به داخل ثبات A می ریزد(pop). و به همین شکل دستور PHP، مقدار ثبات وضعیت را وارد پشته می کند(push) و PLA مقدار بالای پشته را به داخل ثبات وضعیت می ریزد(pop).
نکته: در پردازشگر 6502 دستوری برای وارد کردن مقدار ثابت های X و Y به پشته(push) و یا برداشتن مقدار بالای پشته(pop) و انتقال آن به ثبات های X و Y وجود ندارد. تنها رجیستر انباره(A) می توانید در عملیات push و pop شرکت کند. باید از دستورات انتقال(Transfer) بین ثباتی استفاده کنیم.
مثال: مقدار ثبات X را به داخل پشته منتقل کنید(push)
txa
pha
دستور اول مقدار ثبات X را به A منتقل می کند و دستور دوم مقدار ثبات A را به داخل پشته می ریزد(push).

تمرین: برنامه ای بنویسید که محتویات خانه حافظه های 0380$ و 0381$ را تعویض(Exchange) کند.

راه حل: در پردازشگر 6510 دستوری برای تعویض مقدار دو آدرس از حافظه، وجود ندارد؛ پس ما باید طرحی بریزیم که بتوان محتویات این دو مکان از حافظه را با هم تعویض کرد، در این راه می توانیم از ثبات ها کمک بگیریم. مقدار خانه حافظه 0380$ را در ثبات  X و دومی را در Y بار(LOAD) می کنیم. حال مقدار ثبات  X را در خانه حافظه به آدرس 0381$ و مقدار ثبات Y را در 0380$ ذخیره(STORE) می کنیم. لیست برنامه در زیر می آید:

;Exchange contents of two address
!to "xchg.prg",cbm
*=$033c
ldx $0380
ldy $0381
stx $0381
sty $0380
rts
نکته: می توانیم از ثبات A هم در عملیات تعویض استفاده کنیم.
برنامه را داخل کراس-اسمبلر نوشته و کامپایل کنید سپس فایل اجرایی را با استفاده از دکمه Build & Run روی میله ابزار، بسازید و داخل امولاتور بار کنید. قبل اجرای برنامه زبان ماشین بوسیله دستور SYS، بهتر است خانه حافظه های 380$ و 381$ داری مقدار باشند تا درستی برنامه را به راحتی مشاهده کنید. به وسیله دستور بیسیک POKE یک مقدار بین 0 تا 255 در این آدرس ها قرار دهید. توجه داشته باشید که پارامترهای دستور POKE، بر مبنای 10 هستند نه شانزده.
POKE 896,11: REM 896=$380
POKE 897,66:REM 897=$381
 نکته1: برای جدا کردن دستورات در بیسک از کاراکتر :(Colon) استفاده میکنیم.
 نکته2: عباراتی که بعد از دستور REM قرار میگرند بوسیله مفسر بیسیک نادیده گرفته می شوند و به جهت یادآوری و توضیح برای برنامه نویس کاربرد دارد.
حال با دستور SYS 828، برنامه زبان ماشین را فراخوانی و اجرا کنید. پس از پایان برنامه و بازگشت به محیط بیسک با نگاه(PEEK) به آدرس های  896 و897 می توانید مشاهده کنید که محتویات این دو خانه حافظه تعویض شده است.
PRINT PEEK(896)
66





























(1)
(2)
(3)
(4)

۱ نظر:

  1. ازلی جان رفیق سلام ,کجایی بالاترین پیدات نیست ,امیدوارم هرکجا هستی خوب و خوش و سلامت باشی , همین الان از بالاترین میل داشتم ,همانطور که گفته بودم حساب شما به اشتباه بسته شده بود و ضمن عذرخواهی حساب شما را مجددا باز کرده اند که خواستم به شما اطلاع بدهم ,امیدوارم هرکجا هستی دلت شاد باشه ,در ضمن چون تمام لینکهای که شما نظر داده بودی تو بالاترین به علت گذشت زمان قسمت کامنت ها بسته شده بود راه دیگری واسه اطلاع دادن جز اینجا نبود ولی گویا شما کامنت های زیر پست هات رو هم نمیبینی چون قبلا هم واست کامنت گذاشته بودم ,به هرحال خواستم به شما اطلاع بدهم ,,,ارادتمند جوانشیر

    پاسخحذف

توجه:فقط اعضای این وبلاگ می‌توانند نظر خود را ارسال کنند.