پرش به مطلب اصلی

اسمبلر داخلی

معرفی

این سند به اسمبلر داخلی در زبان Wave می‌پردازد. اسمبلر داخلی یکی از قابلیت‌های ارائه‌شده توسط Wave است که با حفظ سادگی زبان‌های سطح بالا به دسترسی مستقیم به کنترل سخت‌افزاری سطح پایین امکان می‌دهد.

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


دستور زبان پایه

اسم {
"دستورات اسمبلر" // کد واقعی اسمبلر (یک دستور در هر خط)
...
in("رجیستر") مقدار // نگاشت رجیستر ورودی
out("رجیستر") متغیر // نگاشت رجیستر خروجی
}

اجزای دستور زبان

  1. دستورات اسمبلر

    • به صورت رشته متنی "..." نوشته می‌شود و دستورات اسمبلر سطح پایین هستند که در CPU واقعی اجرا می‌شوند.
    • می‌توان چندین خط نوشت، و در هر خط یک دستور نوشته می‌شود.
    • مثال:
      "mov rax, 1"
      "syscall"
  2. in("رجیستر") مقدار

    • مقدار متغیر (یا عبارت) به رجیستر مشخص‌شده بارگذاری می‌شود.
    • مثال:
      in("rdi") s
      -> مقدار متغیر s در رجیستر پارامتر اول syscall در استاندارد x86-64 که رجیستر rdi است، گذاشته می‌شود.
  3. out("رجیستر") متغیر

    • مقدار رجیستر مشخص‌شده به متغیر Wave منتقل می‌شود.
    • مثال:
      out("rax") ret
      -> مقدار رجیستر rax که نتیجه بازگشتی syscall در آن ذخیره شده است، در متغیر ret ذخیره می‌شود.

نمونه ساده

fun main() {
var msg_ptr: ptr<i8> = "سلام از syscall!\n";
var ret_val: i64;

asm {
"mov rax, 1"
"syscall"
in("rdi") 1
in("rsi") msg_ptr
in("rdx") 20
out("rax") ret_val
}
}

ملاحظات

  • اسمبلر داخلی در Wave می‌تواند پایداری نوع را دور بزند، لذا استفاده نادرست از دستورات می‌تواند منجر به پایان غیرعادی برنامه یا وقوع رفتارهای پیش‌بینی‌نشده شود.
  • نگاشت‌های in و out در زمان کامپایل بررسی می‌شوند اما اعتبار خود دستورات تضمین نمی‌شود.