
آموزش رایگان درس برنامه نویسی سیستمی رشته کامپیوتر در دانشگاه
فهرست مطالب
برنامهنویسی سیستمی: مفاهیم و دستورات کلیدی
درس برنامهنویسی سیستمی یکی از دروس اصلی رشته نرمافزار کامپیوتر است که به آموزش مفاهیم بنیادی زبان ماشین و اسمبلی میپردازد. این جزوه، برگرفته از دانشگاه امام محمد باقر ساری، به بررسی دقیق و تخصصی سرفصلهای این درس میپردازد. در ادامه، تمامی سرفصلهای ارائهشده به زبان ساده و با جزئیات کامل شرح داده شدهاند، شامل مبحث جدید تبدیل مبنا و توضیحات گستردهتر برای 25 دستور اسمبلی با مثالهای کاربردی.
درمورد ساخت اپلیکیشن بدون برنامه نویسی بخوانید.
معماری وان نیومن چیست؟
معماری وان نیومن (Von Neumann Architecture) یک مدل طراحی برای کامپیوترهای دیجیتال است که توسط جان وان نیومن در دهه 1940 پیشنهاد شد. این معماری پایه و اساس اکثر کامپیوترهای مدرن را تشکیل میدهد. ویژگیهای کلیدی آن عبارتاند از:
- واحد پردازش مرکزی (CPU): شامل واحد محاسبه و منطق (ALU)، واحد کنترل (Control Unit)، و ثباتها (Registers) برای پردازش دادهها.
- حافظه مشترک: برنامهها و دادهها در یک حافظه مشترک ذخیره میشوند، برخلاف معماری هاروارد که حافظه جداگانهای برای داده و برنامه دارد.
- ورودی/خروجی: امکان دریافت داده از ورودی (مانند کیبورد) و ارسال به خروجی (مانند مانیتور).
- ذخیرهسازی برنامه: دستورات برنامه بهصورت دودویی در حافظه ذخیره میشوند و CPU آنها را به ترتیب اجرا میکند.
- اجرای ترتیبی: دستورات یکی پس از دیگری از حافظه خوانده و اجرا میشوند.
این معماری به دلیل سادگی و انعطافپذیریاش، همچنان در بسیاری از سیستمهای کامپیوتری استفاده میشود، اگرچه محدودیتهایی مانند گلوگاه وان نیومن (Von Neumann Bottleneck) به دلیل دسترسی مشترک به حافظه برای داده و دستورات دارد.

مفسر چیست؟
مفسر (Interpreter) یک برنامه یا ابزار نرمافزاری است که کد نوشتهشده به زبانهای برنامهنویسی سطح بالا یا سطح پایین (مانند اسمبلی) را بهصورت خطبهخط اجرا میکند. برخلاف کامپایلر که کل کد را به زبان ماشین ترجمه میکند، مفسر هر خط را بهصورت مستقیم تفسیر و اجرا میکند.
- ویژگیها:
- اجرای لحظهای کد بدون نیاز به تولید فایل اجرایی جداگانه.
- مناسب برای دیباگ کردن، زیرا خطاها بهمحض وقوع شناسایی میشوند.
- کندتر از برنامههای کامپایلشده، زیرا تفسیر در زمان اجرا انجام میشود.
- کاربرد در اسمبلی: در برنامهنویسی سیستمی، مفسرها برای اجرای دستورات اسمبلی بهصورت خطبهخط در محیطهای توسعه مانند emu8086 استفاده میشوند.
ساختار کامپیوتر
ساختار کامپیوتر به مجموعه اجزای سختافزاری و نحوه تعامل آنها برای اجرای برنامهها اشاره دارد. اجزای اصلی شامل:
- واحد پردازش مرکزی (CPU): مغز کامپیوتر که عملیات محاسباتی و منطقی را انجام میدهد.
- حافظه: شامل حافظه اصلی (RAM) و حافظههای ثانویه (مانند هارد دیسک).
- ورودی/خروجی (I/O): ابزارهایی برای ارتباط با کاربر یا دستگاههای خارجی (مانند کیبورد، ماوس، و چاپگر).
- باس (Bus): مسیری برای انتقال دادهها بین CPU، حافظه، و دستگاههای I/O.
- واحد کنترل: بخشی از CPU که اجرای دستورات را مدیریت میکند.
- ثباتها (Registers): حافظههای کوچک و سریع داخل CPU برای ذخیره موقت دادهها.
این اجزا با هماهنگی یکدیگر، دستورات برنامه را اجرا میکنند و عملکرد کامپیوتر را ممکن میسازند.
انواع حافظه
حافظههای کامپیوتر به دستههای مختلفی تقسیم میشوند که هر کدام نقش خاصی در عملکرد سیستم دارند:
- حافظه اصلی (Primary Memory):
- RAM (Random Access Memory): حافظهای موقت برای ذخیره دادهها و برنامههای در حال اجرا. سریع اما فرّار (با قطع برق دادهها از بین میروند).
- ROM (Read-Only Memory): حافظه فقط خواندنی که دادههای ثابت مانند بایوس را ذخیره میکند.
- حافظه ثانویه (Secondary Memory):
- هارد دیسک (HDD): برای ذخیره دائمی دادهها با ظرفیت بالا.
- SSD (Solid State Drive): سریعتر از HDD و بدون قطعات متحرک.
- فلش مموری و کارتهای SD: قابلحمل و برای ذخیرهسازی دادهها.
- حافظه نهان (Cache Memory): حافظهای بسیار سریع بین CPU و RAM برای دسترسی سریعتر به دادههای پراستفاده.
- ثباتها (Registers): سریعترین نوع حافظه، داخل CPU، برای ذخیره موقت دادهها در حین پردازش.
- حافظه مجازی (Virtual Memory): بخشی از حافظه ثانویه که بهعنوان امتداد RAM عمل میکند.
فرق مفسر، کامپایلر، و زبان اسمبلی
- مفسر (Interpreter):
- کد را خطبهخط اجرا میکند.
- نیازی به تولید فایل اجرایی ندارد.
- کندتر است، اما دیباگ کردن آسانتر است.
- مثال: مفسر پایتون یا ابزارهای دیباگ اسمبلی.
- کامپایلر (Compiler):
- کل کد را به زبان ماشین ترجمه میکند و یک فایل اجرایی تولید میکند.
- سریعتر در اجرا، اما دیباگ کردن پیچیدهتر است.
- مثال: کامپایلر C++ یا اسمبلر برای زبان اسمبلی.
- زبان اسمبلی (Assembly Language):
- یک زبان برنامهنویسی سطح پایین است که مستقیماً با سختافزار ارتباط دارد.
- دستورات آن به زبان ماشین نزدیک هستند، اما خواناتر از کدهای باینری.
- نیاز به اسمبلر دارد که کد اسمبلی را به زبان ماشین تبدیل کند.
- مثال دستورات:
MOV,ADD,SUB.
تفاوت کلیدی: مفسر و کامپایلر ابزارهای ترجمه کد هستند، اما زبان اسمبلی خود یک زبان برنامهنویسی است که به سختافزار نزدیکتر است.
محاسبه دیسکها (ظرفیت هارد)
ظرفیت هارد دیسکها معمولاً بر حسب بایت (Byte) و مشتقات آن (KB, MB, GB, TB) بیان میشود. برای محاسبه ظرفیت:
- واحدها:
- 1 کیلوبایت (KB) = 1024 بایت
- 1 مگابایت (MB) = 1024 کیلوبایت
- 1 گیگابایت (GB) = 1024 مگابایت
- 1 ترابایت (TB) = 1024 گیگابایت
- محاسبه ظرفیت هارد:
- هارد دیسکها معمولاً ظرفیت اسمی (مانند 1TB) دارند، اما ظرفیت واقعی به دلیل فرمتبندی و سیستمعامل کمتر است.
- برای محاسبه دقیق، باید تعداد سکتورها، اندازه هر سکتور (معمولاً 512 بایت یا 4KB)، و تعداد کل بایتها را در نظر گرفت.
- مثال: یک هارد 1TB تقریباً 1,000,000,000,000 بایت ظرفیت دارد.
- کاربرد در برنامهنویسی سیستمی: در زبان اسمبلی، برای مدیریت دیسک، از دستورات سطح پایین و تعامل با بایوس یا سیستمعامل استفاده میشود، مانند خواندن سکتورها با استفاده از وقفههای بایوس.
بایوس چیست؟
بایوس (BIOS – Basic Input/Output System) یک نرمافزار سیستمی است که در حافظه ROM مادربورد ذخیره شده و اولین برنامهای است که پس از روشن شدن کامپیوتر اجرا میشود. وظایف اصلی بایوس:
- بررسی سختافزار (POST): تست اولیه سختافزار (Power-On Self-Test) برای اطمینان از عملکرد صحیح اجزا مانند RAM و CPU.
- هماهنگی سختافزار: مدیریت ارتباط بین CPU، حافظه، و دستگاههای ورودی/خروجی.
- بارگذاری سیستمعامل: انتقال کنترل به لودر سیستمعامل (Bootloader) برای اجرای سیستمعامل.
- ارائه رابط: ارائه خدمات پایه برای سیستمعامل، مانند خواندن/نوشتن دیسک یا مدیریت کیبورد.
بایوس به دلیل نقش حیاتیاش، پایهای برای عملکرد صحیح سیستم است. در سیستمهای مدرن، UEFI جایگزین بایوس شده، اما مفاهیم پایه مشابه هستند.
مکمل دو (2’s Complement)
مکمل دو روشی برای نمایش اعداد منفی در سیستمهای کامپیوتری است که در برنامهنویسی سیستمی و زبان اسمبلی کاربرد زیادی دارد.
- مکمل یک (1’s Complement):
- تمام بیتهای عدد معکوس میشوند (0 به 1 و 1 به 0).
- مثال: برای عدد 0101 (5 در مبنای 2)، مکمل یک میشود 1010 (-5).
- مکمل دو (2’s Complement):
- ابتدا مکمل یک را محاسبه کنید.
- سپس 1 به نتیجه اضافه کنید.
- مثال: برای 0101، مکمل یک = 1010، مکمل دو = 1010 + 1 = 1011.
- روش دیگر: از سمت راست به چپ، بیتها را تا اولین 1 کپی کنید، سپس بیتهای باقیمانده را معکوس کنید.
- کاربرد در ثباتها:
- در ثباتهای 8 بیتی (مانند AL): برای اعداد کوچکتر (مثلاً -128 تا 127).
- در ثباتهای 16 بیتی (مانند AX یا AH+AL): برای اعداد بزرگتر (مثلاً -32,768 تا 32,767).
- مکمل دو برای انجام عملیات حسابی (مانند جمع و تفریق) در CPU استفاده میشود.
- مثال:
- عدد 7 در 8 بیت: 00000111
- مکمل یک: 11111000
- مکمل دو: 11111000 + 1 = 11111001 (-7)
تبدیل مبنا (2 به 8، 2 به 16، و برعکس)
تبدیل مبنا یکی از مفاهیم پایه در برنامهنویسی سیستمی است، زیرا کامپیوترها از مبنای 2 (باینری) استفاده میکنند، اما برای خوانایی، از مبنای 8 (اوکتال) و 16 (هگزادسیمال) نیز استفاده میشود.
1. تبدیل از مبنای 2 به 8 (باینری به اوکتال)
- روش: بیتهای باینری را به گروههای 3 تایی از راست به چپ تقسیم کنید. هر گروه 3 بیتی را به یک رقم اوکتال (0 تا 7) تبدیل کنید.
- جدول تبدیل:
- 000 = 0
- 001 = 1
- 010 = 2
- 011 = 3
- 100 = 4
- 101 = 5
- 110 = 6
- 111 = 7
- مثال: عدد باینری 110101
- گروهبندی: 110 | 101
- تبدیل: 110 = 6، 101 = 5
- نتیجه: 65 در مبنای 8
2. تبدیل از مبنای 2 به 16 (باینری به هگزادسیمال)
- روش: بیتها را به گروههای 4 تایی از راست به چپ تقسیم کنید. هر گروه 4 بیتی را به یک رقم هگزادسیمال (0 تا F) تبدیل کنید.
- جدول تبدیل:
- 0000 = 0
- 0001 = 1
- …
- 1010 = A
- 1011 = B
- …
- 1111 = F
- مثال: عدد باینری 11010110
- گروهبندی: 1101 | 0110
- تبدیل: 1101 = D، 0110 = 6
- نتیجه: D6 در مبنای 16
3. تبدیل از مبنای 8 به 2 (اوکتال به باینری)
- روش: هر رقم اوکتال را به معادل 3 بیتی آن تبدیل کنید.
- مثال: عدد اوکتال 73
- تبدیل: 7 = 111، 3 = 011
- نتیجه: 111011 در مبنای 2
4. تبدیل از مبنای 16 به 2 (هگزادسیمال به باینری)
- روش: هر رقم هگزادسیمال را به معادل 4 بیتی آن تبدیل کنید.
- مثال: عدد هگزادسیمال 2F
- تبدیل: 2 = 0010، F = 1111
- نتیجه: 00101111 در مبنای 2
5. تبدیل از مبنای 8 به 16 و برعکس
- اوکتال به هگزادسیمال: ابتدا به باینری تبدیل کنید، سپس به هگزادسیمال.
- هگزادسیمال به اوکتال: ابتدا به باینری تبدیل کنید، سپس به اوکتال.
- مثال: اوکتال 73 به هگزادسیمال
- اوکتال 73 = باینری 111011
- باینری 111011 = 0011 | 1011 = 3B در هگزادسیمال
نامگذاری تابع
در زبان اسمبلی، نامگذاری توابع (یا رویهها/Procedures) باید واضح و معنادار باشد تا کد خواناتر شود. اصول نامگذاری:
- استفاده از نامهای توصیفی: مانند
CalculateSumبهجایFunc1. - قوانین زبان اسمبلی: نامها باید با حروف یا آندرلاین (_) شروع شوند و از کاراکترهای خاص (مانند @) با احتیاط استفاده شود.
- ثبات در نامگذاری: استفاده از یک سبک ثابت (مانند CamelCase یا snake_case).
- کاربرد: نامگذاری مناسب در دیباگ کردن و نگهداری کد کمک میکند.
- مثال:
CalculateSum PROC ; کد تابع RET CalculateSum ENDP
ساختار عملوندها
عملوندها (Operands) در زبان اسمبلی دادههایی هستند که دستورات روی آنها اجرا میشوند. عملیات منطقی تکعملوندی و دو عملوندی شامل موارد زیر هستند:
- عملیات تکعملوندی:
- NOT: معکوس کردن بیتها (0 به 1 و 1 به 0).
- مثال:
NOT AXتمام بیتهای ثبات AX را معکوس میکند.
- عملیات دو عملوندی:
- AND: اگر هر دو بیت 1 باشند، نتیجه 1 است.
- OR: اگر حداقل یکی از بیتها 1 باشد، نتیجه 1 است.
- XOR: اگر بیتها متفاوت باشند، نتیجه 1 است (یکسان = 0).
- ساختار عملوندها:
- عملوندها میتوانند ثبات (مانند AX)، حافظه، یا مقادیر ثابت باشند.
- مثال:
AND AX, BXعملیات AND را بین ثباتهای AX و BX انجام میدهد.
آدرسدهی در حافظه
آدرسدهی در حافظه به روشهای دسترسی به دادهها در حافظه اشاره دارد. در زبان اسمبلی، آدرسدهی یکی از مفاهیم کلیدی است:
- براکت ([ ]): نشاندهنده محتوای آدرس حافظه است.
- مثال:
MOV AX, [1000h]محتوای آدرس 1000h را به AX منتقل میکند.
- مثال:
- آفست (OFFSET): فقط آدرس یک متغیر را میگیرد، نه محتوای آن.
- مثال:
MOV AX, OFFSET varآدرس متغیر var را به AX منتقل میکند.
- مثال:
- تبدیل آدرس به محتوا: با استفاده از براکت، محتوای آدرس خوانده میشود.
- تبدیل محتوا به آدرس: با استفاده از دستوراتی مانند OFFSET یا LEA.
- تفاوت OFFSET و LEA:
- OFFSET: فقط آدرس ساده یک متغیر را میگیرد.
- LEA (Load Effective Address): میتواند آدرسهای پیچیدهتر (مانند آدرسهای محاسباتی) را محاسبه کند و روی پرچمها تأثیری ندارد.
- مثال:
MOV AX, OFFSET myVar ; آدرس myVar را به AX منتقل میکند LEA AX, [BX+SI+10] ; آدرس محاسباتی را به AX منتقل میکند
دستورات اسمبلی (با مثالهای آموزشی)
در ادامه، 25 دستور اسمبلی با توضیحات کامل و مثالهای کاربردی ارائه شده است. این دستورات برای معماری x86 و در محیطی مانند emu8086 در نظر گرفته شدهاند.
1. MOV
- ساختار:
MOV destination, source - کارکرد: انتقال داده از مبدأ به مقصد بدون تغییر مبدأ.
- مثال:
MOV AX, 5 ; انتقال عدد 5 به ثبات AX MOV BX, AX ; کپی محتوای AX به BX MOV [1000h], AX ; انتقال محتوای AX به آدرس حافظه 1000h - نکته: مقصد سمت چپ و مبدأ سمت راست است.
2. XCHG
- ساختار:
XCHG operand1, operand2 - کارکرد: جابهجایی محتوای دو عملوند.
- مثال:
MOV AX, 10 MOV BX, 20 XCHG AX, BX ; حالا AX=20 و BX=10 - کاربرد: برای جابهجایی سریع مقادیر بدون نیاز به ثبات موقت.
3. OFFSET
- ساختار:
MOV register, OFFSET variable - کارکرد: انتقال آدرس (نه محتوای) یک متغیر به ثبات.
- مثال:
DATA SEGMENT myVar DW 1234h DATA ENDS CODE SEGMENT MOV AX, OFFSET myVar ; AX حاوی آدرس myVar است CODE ENDS - نکته: فقط آدرس را منتقل میکند، نه مقدار.
4. LEA
- ساختار:
LEA register, variable - کارکرد: بارگذاری آدرس مؤثر (Effective Address) یک متغیر یا عبارت در ثبات.
- مثال:
MOV BX, 1000h MOV SI, 10h LEA AX, [BX+SI+5] ; AX = 1000h + 10h + 5 = 1015h - تفاوت با OFFSET: LEA میتواند آدرسهای پیچیده (مانند BX+SI) را محاسبه کند.
5. ADD
- ساختار:
ADD destination, source - کارکرد: جمع منبع با مقصد و ذخیره نتیجه در مقصد.
- مثال:
MOV AX, 10 MOV BX, 5 ADD AX, BX ; AX = 10 + 5 = 15 - ADC (Add with Carry):
- مانند ADD اما پرچم Carry را نیز اضافه میکند.
- مثال:
MOV AX, 0FFFFh MOV BX, 1 ADD AX, BX ; سرریز ایجاد میشود، CF=1 ADC AX, 1 ; AX = AX + 1 + CF
6. SUB
- ساختار:
SUB destination, source - کارکرد: تفریق منبع از مقصد و ذخیره نتیجه در مقصد.
- مثال:
MOV AX, 20 MOV BX, 7 SUB AX, BX ; AX = 20 - 7 = 13
7. INC
- ساختار:
INC operand - کارکرد: افزایش مقدار عملوند به اندازه 1.
- مثال:
MOV AX, 10 INC AX ; AX = 11
8. DEC
- ساختار:
DEC operand - کارکرد: کاهش مقدار عملوند به اندازه 1.
- مثال:
MOV AX, 10 DEC AX ; AX = 9
9. NEG
- ساختار:
NEG operand - کارکرد: معکوس کردن علامت عملوند (مثبت به منفی یا برعکس) با محاسبه مکمل دو.
- مثال:
MOV AX, 5 NEG AX ; AX = -5 (در مکمل دو: 11111011)
10. CMP
- ساختار:
CMP op1, op2 - کارکرد: مقایسه دو عملوند با تفریق (op1 – op2) و تنظیم پرچمها (Zero, Sign, Carry) بدون تغییر مقادیر.
- مثال:
MOV AX, 10 MOV BX, 5 CMP AX, BX ; اگر AX>BX، پرچم Zero=0 و Carry=0
11. MUL
- ساختار:
MUL source - کارکرد: ضرب منبع در AL (8 بیت) یا AX (16 بیت). نتیجه در AX (یا DX:AX برای 16 بیت) ذخیره میشود.
- IMUL: برای اعداد علامتدار.
- مثال:
MOV AL, 5 MOV BL, 3 MUL BL ; AX = 5 * 3 = 15 (000Fh) - برای 16 بیت:
MOV AX, 100 MOV BX, 200 MUL BX ; DX:AX = 100 * 200 = 20000 (4E20h)
12. DIV
- ساختار:
DIV source - کارکرد: تقسیم AX (8 بیت) یا DX:AX (16 بیت) بر منبع. خارجقسمت در AL/AX و باقیمانده در AH/DX.
- IDIV: برای اعداد علامتدار.
- مثال:
MOV AX, 20 MOV BL, 3 DIV BL ; AL = 6 (خارجقسمت)، AH = 2 (باقیمانده)
13. AND
- ساختار:
AND dest, src - کارکرد: عملیات AND بیتبهبیت. نتیجه 1 فقط وقتی هر دو بیت 1 باشند.
- مثال:
MOV AX, 1100b ; 12 در باینری MOV BX, 1010b ; 10 در باینری AND AX, BX ; AX = 1000b (8)
14. OR
- ساختار:
OR dest, src - کارکرد: عملیات OR بیتبهبیت. نتیجه 1 اگر حداقل یکی از بیتها 1 باشد.
- مثال:
MOV AX, 1100b MOV BX, 1010b OR AX, BX ; AX = 1110b (14)
15. XOR
- ساختار:
XOR dest, src - کارکرد: عملیات XOR بیتبهبیت. نتیجه 1 اگر بیتها متفاوت باشند.
- مثال:
MOV AX, 1100b MOV BX, 1010b XOR AX, BX ; AX = 0110b (6)
16. NOT
- ساختار:
NOT operand - کارکرد: معکوس کردن تمام بیتهای عملوند.
- مثال:
MOV AX, 1100b NOT AX ; AX = 0011b
17. SHL
- ساختار:
SHL operand, count - کارکرد: شیفت بیتها به چپ. بیت خروجی به پرچم CF منتقل میشود، بیت سمت راست با 0 پر میشود.
- مثال:
MOV AX, 1100b SHL AX, 1 ; AX = 11000b, CF = 1
18. SHR
- ساختار:
SHR operand, count - کارکرد: شیفت بیتها به راست. بیت خروجی به CF، بیت سمت چپ با 0 پر میشود.
- مثال:
MOV AX, 1100b SHR AX, 1 ; AX = 0110b, CF = 0
19. SAL
- ساختار:
SAL operand, count - کارکرد: شیفت حسابی به چپ، مشابه SHL.
- مثال:
MOV AX, 1100b SAL AX, 1 ; AX = 11000b, CF = 1
20. SAR
- ساختار:
SAR operand, count - کارکرد: شیفت حسابی به راست با حفظ بیت علامت.
- مثال:
MOV AX, 10000010b ; -126 SAR AX, 1 ; AX = 11000001b (-63), بیت علامت حفظ میشود
21. ROL
- ساختار:
ROL operand, count - کارکرد: چرخش بیتها به چپ. بیت خروجی از چپ به راست وارد میشود.
- مثال:
MOV AX, 11000011b ROL AX, 1 ; AX = 10000111b
22. ROR
- ساختار:
ROR operand, count - کارکرد: چرخش بیتها به راست. بیت خروجی از راست به چپ وارد میشود.
- مثال:
MOV AX, 11000011b ROR AX, 1 ; AX = 11100001b
23. RCL
- ساختار:
RCL operand, count - کارکرد: چرخش به چپ با احتساب پرچم CF. ابتدا CF جابهجا میشود.
- مثال:
MOV AX, 11000011b STC ; CF = 1 RCL AX, 1 ; AX = 10000111b, CF = 1
24. RCR
- ساختار:
RCR operand, count - کارکرد: چرخش به راست با احتساب CF.
- مثال:
MOV AX, 11000011b STC ; CF = 1 RCR AX, 1 ; AX = 11100001b, CF = 1
25. TEST
- ساختار:
TEST op1, op2 - کارکرد: عملیات AND بیتبهبیت بدون ذخیره نتیجه، فقط پرچمها را تنظیم میکند.
- مثال:
MOV AX, 1100b MOV BX, 1010b TEST AX, BX ; پرچمها بر اساس 1000b تنظیم میشوند
جزوه های زیر را هم بخوانید:



