سخت‌افزار چگونه از فراخوانی توابع و داده‌های کاراکتری پشتیبانی می‌کند

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

فراخوانی رویهحافظه پشتهکدگذاری کاراکتر

~4 min read · Updated Sep 6, 2026

وقتی یک تابع فراخوانی می‌شود چه اتفاقی می‌افتد

فراخوانی یک Procedure (یک تابع یا زیرروال) به بیش از صرفاً پریدن به کد آن نیاز دارد. پردازنده باید به خاطر بسپارد بعداً کجا برگردد، آرگومان‌های ورودی را منتقل کند، یک نتیجه دریافت کند، و مطمئن شود مقادیر رجیستر کد فراخواننده به‌طور نامحسوس توسط رویه فراخوانده‌شده بازنویسی نمی‌شوند. RISC-V این کار را از طریق یک قرارداد مشخص‌شده انجام می‌دهد، نه سحر و جادوی سخت‌افزاری خاص.

دستور Jump-and-Link

RISC-V یک دستور اختصاصی برای فراخوانی رویه‌ها فراهم می‌کند که به‌طور خودکار موقعیت بازگشت را ذخیره می‌کند:

jal ra, ProcedureAddress

این دستور اجرا را به ProcedureAddress می‌پراند و هم‌زمان آدرس دستور بعدی را در یک رجیستر مشخص، معمولاً به نام ra (return address)، ذخیره می‌کند. وقتی رویه تمام می‌شود، از این آدرس ذخیره‌شده برای پریدن به عقب استفاده می‌کند:

jalr x0, 0(ra)

این کار کنترل را دقیقاً به دستوری که پس از فراخوانی اصلی می‌آید بازمی‌گرداند.

قراردادهای رجیستر برای انتقال داده

برای قابل‌پیش‌بینی نگه‌داشتن فراخوانی رویه‌ها در کامپایلرها و برنامه‌های مختلف، RISC-V از یک Register Convention ثابت پیروی می‌کند:

  • یک بازه مشخص از رجیسترها برای انتقال Argument Values به یک رویه رزرو شده است.
  • یک رجیستر مشخص برای بازگرداندن Result Value به فراخواننده رزرو شده است.
  • برخی رجیسترها Saved Registers نامیده می‌شوند، که یک رویه فراخوانده‌شده باید در صورت استفاده از آن‌ها، پیش از بازگشت آن‌ها را حفظ و بازیابی کند.
  • سایر رجیسترها Temporary Registers هستند، که یک رویه فراخوانده‌شده آزاد است بدون هیچ تعهدی برای بازیابی مقدار اصلی‌شان، آن‌ها را بازنویسی کند.

پشته: مدیریت فراخوانی‌های تودرتو و بازگشتی

یک مجموعه واحد از رجیسترها زمانی که رویه‌ها رویه‌های دیگر را فراخوانی می‌کنند، یا خودشان را به‌صورت بازگشتی فراخوانی می‌کنند، کافی نیست. برای مدیریت این موضوع، RISC-V از ناحیه‌ای از حافظه به نام Stack استفاده می‌کند، که از طریق یک رجیستر اختصاصی Stack Pointer مدیریت می‌شود.

پیش از اینکه یک رویه یک رجیستر ذخیره‌شده‌ای که نیاز به استفاده مجدد از آن دارد را بازنویسی کند، مقدار فعلی آن رجیستر را روی پشته push می‌کند؛ پیش از بازگشت، آن مقدار را با pop کردن بازیابی می‌کند:

رزرو فضای پشته:
addi sp, sp, -8

ذخیره مقدار یک رجیستر:
sd s0, 0(sp)

بازیابی آن بعداً:
ld s0, 0(sp)

آزادسازی فضای پشته:
addi sp, sp, 8

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

نمایش متن: کاراکترها و کدگذاری

فراتر از اعداد، کامپیوترها همچنین نیاز دارند متن قابل‌فهم برای انسان را نمایش دهند. هر کاراکتر منفرد با استفاده از یک استاندارد کدگذاری عددی ذخیره می‌شود، رایج‌ترین آن‌ها ASCII برای متن پایه لاتین یا Unicode برای طیف بسیار گسترده‌تری از خط‌ها و نمادهاست.

یک دنباله از کاراکترها که متن را تشکیل می‌دهند String نامیده می‌شود، و معمولاً به‌صورت بایت‌های پیاپی در حافظه ذخیره می‌شود، یک بایت برای هر کاراکتر، که اغلب با یک مقدار پایان‌دهنده خاص که مشخص می‌کند رشته کجا تمام می‌شود، خاتمه می‌یابد.

چرا این قراردادها اهمیت دارند

چون استفاده از رجیستر و مدیریت پشته از یک قرارداد سخت‌گیرانه و توافق‌شده پیروی می‌کند به‌جای اینکه هر برنامه به‌صورت موردی تصمیم بگیرد، کدی که با کامپایلرهای مختلف کامپایل شده، یا به زبان‌های مختلف نوشته شده، می‌تواند رویه‌های نوشته‌شده توسط یکدیگر را به‌درستی و با امنیت فراخوانی کند — ویژگی‌ای ضروری برای ساخت سیستم‌های نرم‌افزاری بزرگ از اجزای توسعه‌یافته به‌طور مستقل.

Written & researched by Dr. Shahin Siami

Related Articles

تصورات غلط رایج درباره محاسبات موازی و درس‌های نهایی کتاب

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

Continue

واقعیت‌های عملی: بنچمارک CPU در مقابل GPU و ضرب ماتریس چندپردازنده‌ای

مقایسه منصفانه یک CPU و یک GPU نیازمند مدلی است که هم توان عملیاتی محاسباتی و هم محدودیت‌های پهنای باند حافظه را با هم در نظر بگیرد. این مقاله مدل roofline مورد استفاده برای مقایسه سخت‌افزار واقعی مانند Intel Core i7 و NVIDIA Tesla GPU را معرفی می‌کند، سپس نشان می‌دهد ضرب ماتریس چگونه در سراسر چند پردازنده تسریع می‌شود، به‌عنوان کاربرد عملی نهایی مفاهیم موازی این فصل.

Continue

بنچمارک کردن چندپردازنده‌ها و مدل‌سازی کارایی موازی

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

Continue

شبکه‌سازی کلاستر: ارتباط با دنیای بیرون

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

Continue

کلاسترها، کامپیوترهای در مقیاس انبار، و توپولوژی‌های شبکه

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

Continue

مقدمه‌ای بر GPU: موازی‌سازی عظیم برای بارهای کاری سنگین از نظر داده

یک GPU ایده SIMD که پیش‌تر در این مجموعه پوشش داده شد را به یک مقیاس افراطی می‌برد، و هزاران رشته سبک را به‌طور هم‌زمان اجرا می‌کند تا حجم عظیمی از داده مستقل را پردازش کند. این مقاله توضیح می‌دهد چرا GPU ها از نظر معماری این‌قدر با CPU متفاوت‌اند، مدل اجرای رشته آن‌ها چگونه کار می‌کند، و چه نوع بارهای کاری بیشترین بهره را از این طراحی می‌برند.

Continue