انتقل إلى المحتوى الرئيسي

التجميع المضمن

مقدمة

تُكتب التعليمات البرمجية التجميعية في Wave ضمن asm { ... } كتلة. يمكنك التحكم مباشرة في المسجل والذاكرة ومسار استدعاء النظام داخل كود Wave.

الهدف المدعوم حاليًا:

  • Linux aarch64
  • Linux arm64
  • macOS (Darwin) x86_64
  • freestanding aarch64
  • freestanding riscv64
  • freestanding riscv64

لا يتم دعم Windows والأهداف ذات 32-بت حتى الآن.


الشكل الأساسي

يمكن استخدام asm كـ بيان أو تعبير.

asm {
"instruction"
in("constraint_or_reg") value
out("constraint_or_reg") target
clobber("item")
}

عناصر التكوين:

  • سطر النص: تعليمات التجميع الفعلية
  • clobber(...): المعاملات المُدخلة
  • out(...): المعاملات المُخرجة
  • clobber(...): إشارات للتعامل مع السجلات/الحالة/الذاكرة التي قد تتغير

جملة asm

يمكن استخدامه كجملة عادية في حالة عدم وجود قيمة مرتجعة.

var ret: i64 = 0;
asm {
"mov rax, 1"
"syscall"
in("rdi") 1
in("rsi") msg_ptr
in("rdx") 20
out("rax") ret
}

يمكن أن يحتوي out(...) على عدة معاملات.


عبارة asm

يمكن استخدامه كعبارة لتوليد القيم مباشرة.

var result: i64 = asm {
"mov rax, 123"
out("rax") result
};

تنبيه:

  • تسمح عبارة asm بـ out(...) واحد فقط.

قيد in(...) / out(...)

السلسلة لـ in("..."), out("...") هي إحدى الاثنين التالية.

  1. سجل معين
  • مثال: "rax", "rdi", "x0", "w1", "a0", "t0", "x10"
  1. فئة القيود (constraint class)
  • مثال: "r", "m", "rm"

مثال:

in("r") &buf
out("rax") ret
  • المتغير: out("rax") ret
  • إلغاء مرجع المؤشر: clobber(...)

clobber(...)

يمكن أن يقبل clobber(...) عدة عناصر في مرة واحدة ويمكن استخدامها عدة مرات.

asm {
"xor rax, rax"
clobber("rax")
clobber("rcx", "rdx")
clobber("memory")
}

العناصر الرئيسية:

  • السجلات: "rax", "x0" وغيرها
  • المكونات الخاصة: $0, $1 (التنظيم الداخلي حسب الهدف)

يضيف المترجم c بشكل تلقائي clobber الأساسية في الوضع الآمن المتحفظ. (مثل memory, flags/cc وغيرهما؛ في RISC-V freestanding، عادةً تكون memory)


مكان مؤشرات المعاملات ($0, $1, ...)

عند الإشارة إلى المعاملات داخل سلسلة الأوامر، استخدم $N.

asm {
"mov QWORD PTR [$0], 777"
in("r") &buf
clobber("memory")
}

ملاحظة:

  • يتم تحويل النمط %0 تلقائيًا إلى النمط $0 داخليًا.

نطاق الدعم الحالي للمعاملات المدخلة

يدعم حاليًا in(...) الأشكال التالية.

  • معرف المتغير
  • القيمة العددية الثابتة
  • القيمة السلسلية الثابتة
  • &معرف
  • إذابة المرجع للمعرف
  • القيم العددية السالبة/القيم الحقيقية السالبة

قد يتم تقييد التعبيرات العامة المعقدة، لذا ننصح بنقلها إلى متغير مؤقت عند الحاجة.


ملاحظات

تتجاوز التعليمات البرمجية المضمنة لحماية النظام نوعًا ما. قد يؤدي تحديد سجلات خاطئة أو تضارب في القيود أو فقدان clobber إلى خلق تعليمات برمجية غير صحيحة أو تلف في وقت التشغيل.

التوصيات:

  • تحديد ABI والاتفاقيات الخاصة بالنداءات أولاً
  • إدارة السجل الداخلي/الرصاصي وclobber بشكل صريح
  • إذا قمت بالتلاعب بالذاكرة مباشرة، فقم بإعلان clobber("memory") معها.