صداگذاری بازی کامپیوتری در یونیتی – بخش دوم

در بخش گذشته؛ با نحوه صداگذاری و ورود به Trigger و همچنین اضافه کردن موسیقی متن به بازی، آشنا شدیم. در این بخش میخوایم کمی پا رو فراتر بذاریم و Dynamic Soundscape رو هم یاد بگیریم. فقط قبل از اون باید کمی مفاهیم آهنگسازی/صداگذاری رو با هم مرور کنیم.

مفهوم Soundscape

فضاهایی که توسط صدا ساخته میشن، یا بهتر بگم؛ صدایی که باعث میشه فضایی خاص به ذهن ما بیاد رو بهش میگن Soundscape. مفهوم پیچیده‌ای نیست ولی میتونه به پیچیده شدن سایر مفاهیم یا حتی هموار تر شدن فهمشون، کمک کنه.

در تصویر بالا، چند Soundscape رو مشاهده میکنیم. یکی برای موج، یکی برای باد، یکی برای پرندگان و … . اما آیا همیشه Soundscape ها، صداهای محیطی (Ambient ) هستند؟ خیر. بعضی وقتا هم قطعات کوتاه و کوچک موسیقی هستند که به ما در درک شرایط کمک میکنن (برای اهل فنش : مثلا یه ویولن ترمولو که یه آرپژ مینور رو بزنه، میتونه کمی ترس یا نگرانی رو القاء کنه). پس، ما نیاز به Soundscaping داریم که بتونیم با صداها؛ حس القاء کنیم.

مفهوم Dynamic Soundscape

خب اینجا کمی مفهوم میتونه پیچیده باشه، اصلا چرا میگیم داینامیک؟ مشخصه، چون قرار نیست همیشه یکسان باشه. پس به چه دردی میخوره؟ فکر کنید در بازی شما صحنه‌ای وجود داره که قراره صدای آب پخش بشه، پس باید با نزدیک شدن به آب، صدای آب کم کم بلند بشه و به گوش برسه، و وقتی کارمون با اون مرحله تموم شد، صدای آب قطع بشه. این رو بهش میگیم Dynamic Soundscape . در یونیتی به سادگی میتونیم این مفهوم رو پیاده کنیم .

مفاهیم مورد نیاز در یونیتی

مفهوم Audio Mixer

میکسر، مفهومش تقریبا همه جا یکیه، پس اگر با Reaper, FL Studio, Studio One و نرم افزارهای آهنگسازی دیگر (هزاران نرم افزار دیگه!) کار کردید، با این مفهوم آشنایید پس این بخش رو می‌تونید ازش عبور کنید . اما به طور کل، ما از میکسر استفاده میکنیم جهت این که صداها رو به کانالهای مختلف بفرستیم. در این کانال ها میتونیم بلندی صدا، تغییراتشون و همچنین افکتهایی که نیاز داریم رو کنترل کنیم.

در یونیتی هم امکان ایجاد و مدیریت تعداد بسیار زیادی میکسر وجود داره، گذشته از اون ما میتونیم یه سری میکسرها رو Master در نظر بگیریم و یه سری دیگه رو زیرمجموعه اونا حساب کنیم. به این شکل، تقریبا میشه گفت که خود یونیتی داره به ما یه استودیوی کامل صداگذاری رو تحویل میده.

شروع پروژه

خب، اول از فولدر Assets با راست کلیک، یک Audio Mixer ایجاد کنیم و اسمش رو بذاریم Master (قراره همه میکسرهای دیگرمون زیرمجموعه این باشن) :

بعد از منوی Window گزینه Audio Mixer رو فعال میکنیم و به این شکل اون رو خواهیم دید :

حالا که یک Master داریم، دو گروه دیگه (از زیرمجموعه Groups )  ایجاد میکنیم به اسم Soundtrack و Sphere . از Soundtrack برای کنترل موسیقی متن (چطوری؟! یاد میگیریم) استفاده میکنیم و از Sphere برای کنترل موسیقی که کنار Sphere ما پخش میشه.

حالا میریم سراغ دوربینمون و Audio Source ای که بهش اضافه کردیم ، یک گزینه Output داریم، اون رو روی Soundtrack قرار میدیم (به همین راحتی، موسیقی/صدا رو در یک کانال از میکسر فرستادیم!)

و به همین ترتیب، موسیقی که روی Sphere قرار دادیم رو هم به کانال Sphere میفرستیم.

استفاده از Snapshot ها

میکسرها قابلیتی دارن به اسم Snapshot که میتونیم وضعیتی رو از اون میکسرها، ثابت نگه داریم. در واقع انگار که عکس گرفته باشیم (از اسم مشخصه). و به کمک همین Snapshot هاست که میشه وضعیت صدا رو کنترل کرد. در ادامه، کد و روش کار رو با هم یاد میگیریم.

نوشتن اسکریپت Dynamic Soundscape

قبل از هرچیزی، اسکریپتی که در بخش قبل نوشتیم رو از Sphere حذف میکنیم و فایل صوتی رو مستقیم به Audio Source میدیم. سپس به Audio Mixer بر میگردیم و این طور تغییرش میدیم :

با اجرای بازی، الان فقط میتونیم صدای موسیقی متن رو بشنویم. پس میریم به قسمت Snapshots و روی + کلیک می‌کنیم و اسمش رو میذاریم Snap1 . سپس، اون Snapshot ستاره دار (به نوعی Master در اسنپ شاتها!) رو به این شکل تغییر میدیم :

و باز یک Snapshot جدید به اسم Snap2 ایجاد میکنیم. حالا در Asset ها یک C# Script تازه ایجاد میکنیم به اسم DynamicSoundscape . و این ها رو درونش مینویسیم :

در خط چهارم من UnityEngine.Audio رو اضافه کردم، این به این معناست که میتونم از Snapshot ها هم استفاده کنم. در خط ۷ و ۸ هم دو تا Snapshot ساختم به اسم fadeIn (برای آرام بلند شدن صدای مورد نظر) و fadeOut (برای آرام کم شدن صدا)، سپس تعریف کردم که وقتی وارد Trigger شدیم و تگمون هم Player بود، وارد fadeIn بشه و وقتی ازش خارج شدیم، وارد fadeOut . حالا این اسکریپت و دو اسنپ شاتی که ساختیم رو به Sphere میدیم :

حالا وقتشه که بازیمون رو اجرا کنیم و نتیجه رو به چشم ببینیم 🙂

نتیجه کارمون به صورت GIF به این شکله (به تغییر کانالهای میکسر دقت کنید 😀 )

مسلما این همه اون چیزی نیست که برای صداگذاری باید بدونید، ولی به نظر من مهم ترین بخشه. امیدوارم در این دو بخش، تونسته باشم به خوبی پوشش بدم مطلب رو. در آینده هم احتمالا باز مطالبی در مورد کار با یونیتی خواهم نوشت، و اینها آخرین مطالب من در یونیتی نیستن. بهرحال، امید به این که مفید بوده باشه و امید به موفقیت شما 🙂

Share

صداگذاری بازی کامپیوتری در یونیتی – بخش اول

بحث صدا و موسیقی در بازی کامپیوتری، بحث عجیب و گهگاه پرچالشیه. چرا که صداها میتونن جو و هدف بازی ما رو تعیین کنند و بهش فضای بالاتری اختصاص بدن. در این مطلب، قصد دارم بخشی از تجربیات خودم در زمینه صداگذاری (و نه آهنگسازی!) در بازی های کامپیوتری رو با شما به اشتراک بذارم. در این مطلب، چیزی که بررسی میکنیم : ۱. قرار دادن موسیقی متن بازی و ۲. پخش صدا در Trigger های خاص خواهد بود. پس در ادامه با من باشید 🙂

قرار دادن موسیقی متن بازی

اول یک پروژه به اسم Audio Test درست میکنیم، سپس وارد Scene اصلی میشیم تا این صفحه یونیتی رو ببینیم :

حالا باید دو کار انجام بدیم، از Asset های پیشفرض، یک First Person Controller برداریم و Main Camera رو هم پاک کنیم. ضمن این که لازمه حتما یک «زمین بازی» بسازیم. بعد از این کارها Scene من این شکلی شد :

وقتی روی FPSController کلیک کنیم و اولین زیرمجموعه‌ش رو در Inspector ببینیم با این صحنه مواجه میشیم :

همونطور که می‌بینید، در این Inspector ما عنصری به اسم Audio Listener داریم. Audio Listener کارش «شنیدن صدا»ست و روی دوربین سوار میشه. کاراکتر اول شخص هم معمولا همراه خودش یک دوربین داره، پس خیالمون از بابت «شنیده شدن» صدا، راحته. حالا روی Add Component کلیک می‌کنیم و یک Audio Source بهش اضافه میکنیم و سپس، موسیقی متن مورد نظر رو به عنوان Audio Clip بهش معرفی می‌کنیم (در اینجا دوئت پیانو و ویولن که چند وقت پیش ساخته بودم رو معرفی کردم) و تیک Loop هم میزنیم :

(البته اینجا تیک Loop رو نزدم) و حالا تبریک! موسیقی متن بازی شما نشست روی بازی. ولی این همه ماجرا نیست. ماجرا در کل خیلی پیچیده تر میشه ولی این اولین چیزیه که ما باید یاد میگرفتیم (مثلا بعدها در مورد این که چطور موسیقی داینامیک استفاده کنیم و … هم بحث خواهد شد).

حالا که این رو یاد گرفتیم، بریم سراغ اضافه کردن یک لایه صدا که در یک Trigger خاص قرار می‌گیره.

ساخت Trigger های صدا

در Scene یک Sphere میسازیم، یک متریال دلخواه بهش میدیم، یک Collider از نوع Trigger براش تعریف می‌کنیم و نتیجه میشه این :

خب، محتوای Inspector باید مثل این باشه (البته الزامی نیست، صرفا خواستیم که محدوده Collider مشخص باشه). الان کاری که باید بکنیم، اینه که یک Audio Source و یک Script به این Sphere اضافه کنیم (زبان اسکریپت رو سی‌شارپ تعیین کنید). حالا کافیه در اسکریپتمون چنین چیزی بنویسیم :

این اسکریپت، میگه که «اگر چیزی وارد Collider من شد و تگ Player داشت، کلیپی که معرفی شده رو یک بار پخش کن». پس به Inspector باید بریم و برای FPSController مون، یک تگ Player تعریف کنیم. سپس، به Script (و نه Audio Source ) باید یک Clip اختصاص بدیم، به این شکل :

و خب کار تموم شد! این فایل صوتی هم با ورود ما به Trigger تعریف شده، پخش خواهد شد!

چه چیزهایی مونده که هنوز باید یاد گرفت؟

موضوعی که اینجا بهش پرداخته شد خیلی خیلی سطحی بود. برای کار صدا در یونیتی، هم باید با Audio Mixer کار کنیم هم Audio Mixer Snapshot . گذشته از اون، باید با اسکریپت؛ اینها رو به هم مرتبط کنیم، به شکلی که یه جا موسیقی آروم قراره پخش بشه و بعد موسیقی یک صحنه خوفناک وارد بشه و … . سعی می‌کنم در قسمت (های) بعد، این موارد رو هم پوشش بدم.

موفق باشید 🙂

Share

امنیت حسابهای اجتماعی

امروز صبح در تلگرام پیامی برای من فوروارد شد که حاوی یک اسکرین شات از توییت خود شرکت توییتر بود. این اسکرین شات :

همونطوری که می‌بینید، توییتر میگه یک باگ پیدا کردن که باعث شده یک سری پسوردها، بدون این که ماسک بشن، لاگ شدن. یعنی چی؟

فرض کنیم ما یک پسورد میسازیم، پسورد ما موقعی که داریم وارد میکنیم یک چیزی مثل MySecurePassword@123456 عه. این پسورد تقریبا تمام فاکتورهای یک پسورد امن رو داره. ولی اگر به صورت Plain Text بخوایم ذخیره‌ش کنیم این که جای خود، یک میلیون کارکتر دیگر هم داشته باشه احتمال لو رفتنش بسیار بالاست. (داخل پرانتز عرض کنم خدمت آقای علیرضا شیرازی، مدیریت محترم بلاگفا که تا چند سال پیش هم همینطوری پسورد ها رو نگهداری میکرد، جای این که در توییتر و … ملت رو بخاطر مواخذه کردنتون بلاک کنید، پاسخ میدادید که چرا اینطور بود! چون همون موقع هم بسیاری از اسکریپت های مدیریت محتوا پسوردها رو ماسک می‌کردن!).
حالا بخوایم MySecurePassword@123456 رو در دیتابیسی ذخیره کنیم باید چه کنیم؟ باید از «هش» و الگوریتم های مربوطه استفاده کنیم. مثلا الگوریتم MD5 (لینک جهت مطالعه). حالا این عبارت نسبتا سخت رو من با کمک ابزارهایی که دم دستم بود به MD5 هش میکنم و نتیجه میشه :

23b7618b2a23e171e6cda057a9736423

و وقتی من پسورد رو وارد کنم، اسکریپتی که برای لاگین نوشتم، یا API ای که وظیفه لاگین کردن من رو برعهده میگیره، اول پسورد رو هش میکنه بعد در دیتابیسش چک میکنه و اگر هش یکی بود، اجازه میده من به سیستم دسترسی داشته باشم. برای مثال این یک سیستم لاگین بسیار ساده بود که خودم نوشته بودم :

کد   
post '/welcome' do
 begin 
  params[:user][:password] == params[:user][:password_again]
  user = User.create(:username => params[:user][:username], :password => Digest::MD5.hexdigest(params[:user][:password]))
  redirect to("/welcome")
 rescue
  redirect to("/signup_error")
 end
end

و این یعنی ذخیره ایمن پسورد در یک دیتابیس (در اینجا از دیتابیس های مونگو استفاده کردم). و حالا اگر اون قسمتی که مربوط به هش کردن پسورد نمیشد رو، در کد قرار میدادم چه میشد؟ وقتی قرار بود Query بزنم مثلا به یوزر mamad و پسوردش 1125 بود، اینطور بر میگردوند :

کد   
{
"username":"mamad", 
"password":"1125"
}

و مثلا اگر شما قرار بود با API ای که من برای عضوگیری سرویس نوشتم کار کنید (مثلا لاگین کردن به وسیله سرویس من در اپلیکیشن، بازی یا سیستم حضور غیاب و … )، پسوردها رو به سادگی میتونستید ببینید. اما چیزی که الان بر میگرده اینه :

کد   
{"username":"mamad","password":"c21002f464c5fc5bee3b98ced83963b8"}

و خب شما نمیتونید به پسورد دسترسی پیدا کنید، مگر این که ابزار یا دیکشنری مربوط به شکستن این الگوریتم رو داشته باشید. البته معمول هم نیست شما JSON مربوط به اطلاعات کاربران رو برگردونید! چون باز هم دیتای کاربر به خطر میفته.

فکر کنم به قدر کافی در مورد پسورد و نحوه ذخیره سازیش توضیح داده باشم، هدف این بود که مباحثی مربوط به هک شدن و نفوذ به تلگرام هم در این پست مطرح کنم که متاسفانه این پست بیش از چیزی که فکر کردم، طولانی شد. پس در مورد تلگرام در پست جداگانه ای خواهم نوشت 🙂

 

Share

مرگ وبلاگ نویسی، گشت و گذاری در سرویس های وبلاگ فارسی

شاید حدود ۱۰ سال پیش، وقتی به تازگی وارد ۱۲ سالگی شده بودم، شروع به ساخت وبلاگ در یکی از قدیمی ترین سرویس های وبلاگدهی فارسی، یعنی بلاگفا کردم. بلاگفایی که تا همین یکی دو سال پیش، به معنای واقعی از پرترافیک ترین وبسایت های فارسی به شمار میرفت.
دقیقا همان روزها، بلاگفا در صفحه اصلیش، دست کم دو تبلیغ نشان میداد، اخبارش و وبلاگ های بروز شده را لیست می‌کرد و گهگاه در شکل خبرهای فوری، امکانات حذف یا اضافه شده به سیستمش رو اطلاع رسانی می‌کرد. به این شکل مثلا فهمیدیم که مدتی blogfa.ir هم در دسترسه، و هر وبلاگی که شما بسازید هم در زیردامنه blogfa.com و هم blogfa.ir قرار میگیره.
البته، آن روزها پرشین بلاگ (قدیمی ترین سیستم بلاگدهی فارسی) و بلاگ اسکای و … هم رونق زیادی داشتند. در واقع، هرکس که میتونست هزینه های یک سرویس بلاگدهی (بخاطر سرور و منابع بالایی که نیاز داره و … ) رو تامین کنه و دانشی از برنامه نویسی وب داشت، یک سیستم بلاگدهی بالا میاورد. اما اونهایی که خیلی مطرح بودند، همین بلاگفا و بلاگ اسکای و پرشین بلاگ بودند.
دوستانی هم بودند که ترجیح میدادند – علیرغم فیلترینگ – از سرویس هایی مثل وردپرس یا بلاگر استفاده کنند، و ما هم با سختی و زحمت هایی که اون زمان برای عبور از سد داشتیم، وبلاگ ها رو میخوندیم و گهگداری هم اینتراکشنی داشتیم.

اما الان چه بلایی سر بلاگ ها اومده؟ امروز بعد از چند سال صفحه اصلی بلاگفا رو باز کردم! دیدم دیگه خبری از اخبار و لیست بلاگهای بروز شده نیست، همه‌ش شده لینک در صفحه اصلی، و صفحه اصلی صرفا شده یه محل برای لاگین کردن وبلاگ نویس ها!
لیست وبلاگ های بروز شده رو باز کردم و یکی دو تا وبلاگ رو خوندم، یکیشون دقیقا همین دهم آبان ویرایش شده بود و یکی هم حدود سه روز پیش. قبلا، این بروزرسانی ها، ساعتی بود. مثلا الان لیست رو میخوندیم، میدیدیم که در ۴ ساعت گذشته دست کم ۱۰ وبلاگ بروزرسانی شدند، اما الان این اختلافها به روز رسیدند!

گرچه، دلیل «مرگ وبلاگ نویسی» مشخصه، دیگه کسی نمیره از بلاگفا سرویس بگیره و بلاگ بنویسه، معمولا یه کانال تلگرامی میزنن و حرفاشون رو اونجا میزنن، دریغ از این که نمیدونن موندگار نیست، حداقل اونقدری که وبلاگ های روی بلاگفا هستند!

Share

آغاز به یادگیری هوش مصنوعی

در پست قبلی وبلاگ، در مورد چیستی هوش مصنوعی توضیح دادم. در این یکی پست، قصدم اینه که به شما بگم برای یادگیری هوش مصنوعی لازمه چه چیزهایی بلد باشیم و چه چیزهایی رو در طول زمان یاد میگیریم. خب، پس بریم سراغ این که برای هوش مصنوعی چه پیش‌نیازی لازمه، بعد کم کم بریم سراغ سیر یادگیری و … .

  • الگوریتم:
    این که بتونید برای یک برنامه، یک الگوریتم بهینه پیدا کنید یا پیشنهاد بدید، مهم ترین عامل در یادگیری و انجام پروژه های هوش مصنوعی به حساب میاد. اگرچه این مورد، همه جا کاربرد داره و کلا برای برنامه نویس و دولپر خوب شدن لازمش داریم؛ ولی اینجا لازمه که به الگوریتم و الفبای موضوع مسلط باشیم. پس، باید یاد بگیریم که چطور با استفاده از الگوریتم ها یک برنامه بسازیم. خب برای یادگیری الگوریتم (اگر بلد نیستید) پیشنهاد من کتاب CLRS هست. هم ترجمه این کتاب در بازار موجوده و هم زبان اصلیش در اینترنت هست.
  • برنامه نویسی :
    برای این که بتونید پروژه هوش مصنوعی انجام بدید باید برنامه نویسی بلد باشید؛ بهرحال بخشی از کامپیوتره و نمیشه ازش در رفت. گرچه ممکنه شما صرفا ایده پردازی یک پروژه هوش مصنوعی رو انجام داده باشید ولی موضوع مهم اینه که شما بتونید همون ایده رو هم چندین بار تست کنید و بعد ارائه‌ش کنید به یک تیم. پس، برنامه نویسی بلد بودن هم از شرایط یادگیری و انجام پروژه در هوش مصنوعی هست. پیشنهاد من هم برای یادگیری زبان، پایتونه که الان تبدیل شده به ابزار شماره یک پروژه های هوش مصنوعی.
  • علوم شناختی :
    علوم شناختی یا Cognitive Science ترکیبیه از روانشناسی، فلسفه ذهن، زیست شناسی مغز و علوم کامپیوتر. البته انقدر ها هم خلاصه نیست و من دارم انقدر خلاصه میگم. برای این که بتونیم پروژه های هوش مصنوعی بزنیم؛ لازم داریم که بلد باشیمش. گرچه طوریه که در حین یادگیری هوش مصنوعی هم، این موضوع رو یاد میگیریم. خیلی از ایده ها و … که در هوش مصنوعی (به ویژه شبکه های عصبی مصنوعی) مطرح شده، حاصل کار دانشمندان شناختی بوده.
شبکه عصبی مصنوعی
شبکه عصبی مصنوعی

 

  • با مغز انسان آشنا بشید!
    این مورد از مهم ترین مواردی هست که باید به عنوان کسی که کار هوش مصنوعی میکنه، بلد باشیم. کاری که ما میخوایم بکنیم این هست که یک سری اعمال انسانی مثل تفکر، تصمیم گیری و یادگیری رو برای ماشین پیاده سازی کنیم و ماشین ما قراره فکر کنه برای ما. پس، بهتره که ساختار مغز رو بشناسیم و باهاش آشنا بشیم. در این زمینه هم کتاب و رفرنس زیاد داریم.
  • از منابع مختلف استفاده کنید!!!
    و در آخر هم، استفاده از منابع متعدد مثل یوتوب، وبسایت های هوش مصنوعی و کتابها توصیه میشه. به این شکل شما میتونید به راحتی و بدون هیچ مشکلی، هوش مصنوعی یاد بگیرید و از انجام پروژه های هوش لذت ببرید.
Share

پروژه گاه‌شمار

خب، من در گروه های تلگرامی این پیام رو میذاشتم :

دوستی مدتی پیش (که خیلی هم ازش نگذشته ) یک چالش رو بعنوان تمرین برنامه نویسی پیشنهاد داد، و اون هم نوشتن یک API بود برای دریافت ساعت و تاریخ.
من هم وارد این چالش شدم و یک API با روبی و سیناترا نوشتم، روی گیتهاب هم قرارش دادم ولی الان دپلویش کردم که اگر شما هم خواستید بتونید ازش استفاده کنید :
https://gahshomar-api.herokuapp.com/

خب، این هم پروژه ای بود که محسن بعنوان تمرین خواست که ما یه API بنویسیم، من هم این رو با Sinatra نوشتم و الان دپلوی شده و در دسترسه! امیدوارم ازش لذت ببرید 🙂

Share

زبان ماشین، رمزگشای دستور العمل

در پست های گذشته بسیار بسیار در مورد زبان ماشین و اسمبلی بحث کردیم، اما این بار میخوایم بررسی کنیم که یک دستور، چطور کار میکنه. برای این کار، ما از ساده ترین دستورات استفاده میکنیم. قبل از اون، باید ببینیم که چه اتفاقی میفته که دستورات ما، شناسایی میشن! پس میایم و دستوراتمون رو بررسی میکنیم.

یک دستور در ماشین چطور خونده میشه؟

این خیلی مهمه که بدونیم یک دستور به چه شکلی خونده میشه. بسیار خوب، دستور زیر رو در نظر بگیرید :

کد   
MOV AX, 0

 

این دستور ماشین کد به این شکل داره :

کد   
B8 0000

 

که البته این ماشین کد، یک ماشین کد هگزادسیمال هست. اون چهار صفری که داریم که مقداری هست که خواستیم توی AX قرار بدیم و باهاش کاری نداریم، ولی B8 ما ، همون دستوریه که لازمه رمزگشایی شه و به صورت دو دویی به این شکل در میاد :

کد   
1011 1000

 

خب ما یک «دیکدر» (که یک مدار متشکل از n ورودی و دو به توان n خروجی هست) داریم، که این اعداد رو به ترتیب روشن و خاموش میکنه، و به این شکله که ما به  دستور میرسیم. در واقع مدارات مربوط به دستور رو خواهیم داشت.

بسیار خوب، حالا که میدونیم چه چیزی باعث میشه که ما بتونیم زبان ماشین رو درک کنیم، بیایم بررسی کنیم که :

زبان ماشین از چند بخش تشکیل شده؟

زبان ماشین، اول به صورت اسمبلی نوشته میشه که به زبون انسان خیلی خیلی نزدیکه. یعنی هرکس کمی انگلیسی بدونه میدونه که کلمه ای مثل ADD یعنی جمع کردن. اما، حالا مشکلی که هست اینه که وقتی «اسمبلی» به «آبجکت کد» یا همون کد هگزادسیمال تبدیل میشه رو هرکسی نمیتونه بخونه. پس راه حل چیه؟

اول باید ببینیم که یک خط آبجکت کد از چیا تشکیل میشه! بیاید این مثال رو در نظر بگیریم باز :

کد   
MOV AX, 0 ;B8 0000

 

خب اینجا من آبجکت کد رو به صورت کامنت در آوردم. دو بخش داریم، یکیش چهارتا صفر، که بهش عملوند یا Operand میگیم و دیگری «کد عملیات» یا Operation Code هست. مثلا برای انتقال به AX همیشه از B8 استفاده میشه. چرا؟ چون اینتل اینطور خواسته 😀 . بعد از این، این کد هگزادسیمال به یک کد باینری تبدیل میشه که CPU میتونه اون رو برای ما اجرا کنه.

از کجا آبجکت کد رو بخونیم؟

همه اسمبلر های موجود میتونن فایلی تولید کنن که آبجکت کد، سمبلهای به کار رفته و … رو شامل شه، و در اسمبلر MASM این فایل با پسوند LST ساخته میشه. شما میتونید با باز کردن این فایل با یک ویرایشگر متنی و خوندنش، ببینید که هر دستوری چه کدی رو داره.

یک برنامه نمونه

خب، من یک برنامه اسمبلی خیلی ساده نوشتم که اجرا کردنش هیچ خروجی ای نداره (:D ) ولی خب آبجکت کد ها تولید شده و اسمبل بدون مشکل صورت گرفته. این برنامه با آبجکت کدهاش به صورت کامنت به این شکله (بررسی دستور MOV در ۱۲ حالت مختلف) :

کد   
.MODEL SMALL
.8086
.STACK 
.DATA
.CODE
MOV AX, 0 ;B8 0000
MOV BX, 0 ;BB 0000
MOV CX, 0 ;B9 0000
MOV DX, 0 ;BA 0000
MOV AH, 0 ;B4 00
MOV BH, 0 ;B7 00
MOV CH, 0 ;B5 00
MOV DH, 0 ;B6 00
MOV AL, 0 ;B0 00
MOV BL, 0 ;B3 00
MOV CL, 0 ;B1 00
MOV DL, 0 ;B2 00
END

برای جلوگیری از ابهام هم مقداری که توی رجیسترها ریخته شده صفر هست، به این شکل کد ماشین بسیار ساده تر شده.

تا پست های بعدی، و اسمبلی بیشتر، موفق و موید و آزاد و شاد باشید! 🙂

Share

گسترش Makefile ها – استفاده از متغیر در Makefile

توی این پست بود که تصمیم گرفتم در مورد نوشتن Makefile توضیح بدم. اما قضیه نوشتن میک فایل، به اون چیزی که اونجا مطرح کردیم محدود نمیشه. میتونیم توی Makefile هامون تعدادی متغیر داشته باشیم. متغیر میتونه کامپایلرمون، ورودی ها و خروجی هاش رو مشخص کنه. حتی سوییچ هایی که برای کامپایل کردن برنامه نیاز داریم میتونیم توی Makefile قرار بدیم. بسیار خوب، خود میک یه دستور echo هم داره که میتونیم برای چاپ پیام ازش استفاده کنیم (به جای استفاده از echo بش). حالا سوال پیش میاد که چطور از این دستور ها و قابلیت ها استفاده میکنیم؟

این خط رو در نظر بگیرید :

کد   
gcc -std=c99 main.c mpc.c -ledit -lm -o main -Wincompatible-pointer-types

الان ما میتونیم هرچی که با L شروع میشه رو توی یک متغیر بریزیم، std رو هم همینطور و همچنین incompatible-pointer-types رو. اینطوری چه سودی بهمون میرسه؟ یک میک فایل تر و تمیز خواهیم داشت. پس به این شکل توی میک فایلمون درش میاریم :

کد   
CC = gcc
STD = -std=c99
LINK = -ledit -lm
FLAGS = -Wincompatible-pointer-types

الان هرچی که لازم بود رو توی متغیرهامون گذاشتیم، ولی نوع استفاده از متغیر هم مهمه. همون کد بالا رو در نظر بگیرید، حالا میایم از متغیرها استفاده میکنیم و به چنین چیزی میرسیم:

کد   
$(CC) $(STD) main.c mpc.c $(LINK) -o main $(FLAGS)

دقت کنید که پرانتز هم برای صدا زدن متغیرها لازمه. الان ما یک میک فایل تر و تمیز داریم. کل میک فایلمون به این شکل در اومده الان :

کد   
CC = gcc
STD = -std=c99
LINK = -ledit -lm
FLAGS = -Wincompatible-pointer-types
all:
	$(CC) $(STD) main.c mpc.c $(LINK) -o main $(FLAGS)
 
clean:
	rm main

خب الان میخوایم یک پیام هم چاپ کنیم و به کاربر خوش آمد بگیم، یا بگیم که صبور باشه و بعد کامپایل شدن پیام کامپایل با موفقیت رو چاپ کنه! کافیه به این فرمت چیزی که میخوایم رو بنویسیم:

کد   
@echo "Compiling proccess may take a long time, please be patient"

و به این شکل پیامتون رو هرجا که دوست داشتید قرار بدید. البته Makefile های خیلی خیلی گسترده تر هم وجود دارند که به معنای واقعی میشه گفت یک کمپانی کامپایل هستند.

امیدوارم که این پست هم مفید واقع شده باشه، چون واقعا رفرنس برای نوشتن Makefile توی اینترنت نیست.

موفق و پیروز باشید 🙂

Share

ساخت کراس کامپایلر GCC

اگر لینوکسی باشید (یا حداقل با یکی از سیستم عاملهای خانواده *NIX کار کرده باشید) ، به احتمال خیلی زیاد GCC رو میشناسید. GCC که مخفف GNU Compiler Collection هست یک کامپایلر بزرگ، یا بهتر بگیم یه مجموعه از کامپایلرهاست که توسط پروژه گنو ارائه شده. این کامپایلر به صورت پیشفرض روی تمام توزیع های لینوکس هست (چون چیزیه که عمده ابزارهای لینوکس باهاش کامپایل شدند) و احتمالا روزهای اولی که خواستید توی لینوکس کد C بزنید با این کامپایلر بوده و البته کلی هم فحش دادید بهش 😀 . اگر کمی پیش بریم و برسیم به کسایی که تجربه ساخت LFS رو داشتن، اونها هم احتمالا با کامپایل کردن GCC مواجه شدن. شاید نفس گیر ترین بخش ماجرا در LFS همین GCC باشه ، چون هم طولانیه و هم کلی کانفیگ داره! . اما خب کراس کامپایلر قضیش یکم متفاوته.

من چند وقتیه (خیلی وقته!) درگیر ساخت یک سیستم عاملم و کلی هم برای خودم تحقیق کردم و داکیومنت خوندم و حتی داکیومنت هام رو بازنشر دادم. اما مشکل اینجاست که سیستم عامل قبلیمون کاملا با اسمبلی بود ولی این یکی رو میخوایم با C پیاده سازی کنیم. به نظرتون چی میشه؟ هیچی نمیشه! فقط نیاز داریم تا به جای این که صرفا از NASM استفاده کنیم، جناب GCC که برای خودش غولیه رو هم بازی بدیم. اما اگر سیستممون ۶۴ بیتی باشه چطور؟ اصلا اگر سیستم عامل مقصدمون برای پردازنده ای مثل ARM نوشته شده باشه چی؟ برای این که بتونیم نتیجه و خروجی درست و حسابی بگیریم، نیاز داریم تا کراس کامپایلر داشته باشیم. (برای دونستن اهمیت کراس کامپایلر این لینک رو بخونید).

خب GCC برای کامپایل شدن به Binutils نیاز داره. همچنین قبل از کامپایل Binutils برای معماری مورد نظرمون، باید این کتابخونه ها رو نصب کنیم :

کد   
sudo apt-get install libgmp3-dev libmpfr-dev libmpc-dev texinfo

خب، حالا که این کتابخونه ها رو نصب کردیم میریم که محیط ساخت و ساز (ممکنه درست نباشه ولی باحال ترین معادل ممکن برای Build Environment بود!) رو فراهم کنیم. من میخوام gcc من، برای i686-elf کار کنه. همچنین نمیخوام خیلی پر و بال بدم به ماجرا و نصب رو راحت و با کاربر خودم انجام بدم، پس این کد ها رو وارد ترمینال میکنم تا توی همون پوشه خونگی، gcc مورد نظرمون قرار بگیره!

کد   
export PREFIX="$HOME/opt/cross"
# فراموش نکنید این پوشه رو خودتون باید بسازید 🙂
export TARGET=i686-elf
export PATH="$PREFIX/bin:$PATH"

خب، حالا باید binutils رو از اینجا و gcc رو هم از اینجا دانلود کنید، و سورس ها رو درون پوشه ای به اسم src قرار بدید (پوشه src داخل پوشه خونگی شما قرار داره!). بسیار خوب! توی پوشه src پوشه ای بسازید به اسم build-binutils و سپس سورس binutils رو از حالت فشرده خارج کنید. حالا وارد پوشه build-binutils بشید (هیچی رو وارد این پوشه نکنید!) و سپس تایپ کنید :

کد   
../binutils-*/configure --prefix="$PREFIX" \
--target=$TARGET \
--with-sysroot --disable-nls --disable-werror

بعد از زدن این دستور، اسکریپت configure براتون Makefile درست میکنه. من از نسخه ۲.۲۵ استفاده کردم و واقعا بی مشکل بود، شما هم بهتره از همین نسخه استفاده کنید. حالا که Makefile برامون تولید شده کافیه به ترتیب make و سپس make install رو تایپ کنیم تا binutils مون نصب شه. حالا نوبتی هم باشه نوبت gcc دوست داشتنیه!

خب پوشه build-gcc هم بسازیم و بریم داخلش! حالا باید از فایل configure دوباره برای ساختن Makefile استفاده کنیم!

کد   
../gcc-*/configure --prefix="$PREFIX" \
--target="$TARGET" \
--disable-nls \
--enable-languages=c,c++ \
--without-headers

بعد از انجام این مرحله، باید یکی یکی دستورات زیر رو بزنیم :

کد   
make all-gcc
make all-target-libgcc
make install-gcc
make install-target-libgcc

تا gcc برامون نصب شه! الان با فراخوانی دستوری مثل i686-elf-gcc ، میتونیم به gcc ساخته شدمون دسترسی پیدا کنیم!

امیدوارم که این مطلب مفید واقع شده باشه، موفق باشید 🙂

Share

بازی با سوییفت

زبان برنامه نویسی سوییفت ، زبانی که اپل ارائه کرده و همچنین به تازگی هم اوپن سورس شده. این زبان یه زبان باحال، قشنگ و خوش ساخته، و البته قشنگی ماجرا اینه که خیلی راحت میشه روی لینوکس یا FreeBSD و … هم اجراش کرد. فرمورک Foundation هم که یکی از فرمورکهای کلیدی اپل بوده، برای این زبان به صورت اوپن سورس ارائه شده، و این یعنی اوپن سورس بیش از پیش بهشت برنامه نویسان شده (با این حساب حتی اگر دیوایس اپل ندارید میتونید این زبان رو یاد بگیرید و تمرین کنید). بسیار خوب، بریم سراغ این که ببینیم این زبان چه شکلیه و چطوریه! اول از همه این که سینتکس کاملا شبیه Objective C داره، و اگر قبلا آبجکتیو سی کد زدید، سوییفت یاد گرفتن براتون بی نهایت آسون میشه. خب، اولین مثال و به نوعی مثال روتین برای آشنا شدن با یک زبان، یا همون «سلام دنیا» (که در مقاله پیشین بهش اشاره شد) ، به این شکله :

کد   
print("Hello, World!")

خب، این روش برای چاپ رشته خیلی مرسومه (استفاده از یه تابع چاپ و یک رشته) ، اما برای این که مفاهیم بهتر منتقل شن، میتونیم رشته رو داخل یک متغیر بریزیم :

کد   
var welcomeMessage: String = "Hello, World"

خب الان که متغیر welcomeMessage رو داریم میریم که چاپش کنیم :

کد   
print(welcomeMessage)

خب میخوایم بریم سراغ چیزایی که توی یه زبان خیلی مرسومن، مثلا حلقه while و این چیزا! خب اگر C و Objective C و این زبانا رو بلد باشید خیلی کارتون راحته چون دقیقا همونه :

کد   
while(true){
 print(welcomeMessage)
 }

خب این هم چاپ بی نهایت همون پیامی که توی متغیر welcomeMessage ریختیم 😀 . برای اطلاعات بیشتر از ساختارهای کنترلی میتونید این لینک رو بخونید.

بسیار خوب، ساختار فانکشن ها هم همونطور شبیه C و Objective C و البته شبیه Go هم هست! این یه تابع بازگشتیه (که البته توی REPL زبان خیلی اذیتم کرد ولی موقع کامپایل خیلی مظلومانه (:D) اجرا شد!

کد   
func factorial(x: UInt) -> UInt {
 if(x == 0) {
   return 1
   } else {
   return x * factorial(x - 1)
   }
 }

خب این تابع یک عدد صحیح بدون علامت رو میگیره و فاکتوریلش رو حساب میکنه و بعد بر میگردونه، همونطور که دیدید اگر با زبان های شبیه C آشنا باشید خواهید دید که تقریبا هیچ فرق خاصی از نظر سینتکس نداره. فقط باید یک مقدار روی دیتاتایپ ها و … دقیق بشید تا بفهمید قضیه چیه وگرنه در کل اصلا زبان سختی نیست. اگر میخواید یادش بگیرید کتابی که خود اپل ارائه کرده رو میتونید دریافت کنید (روی iBooks هم هست!).

امیدوارم که این مطلب مفید واقع شده باشه.

موفق باشید 🙂

Share