PDA

View Full Version : Inline Assembly with AT&T



homan11
شنبه 02 فروردین 1393, 18:58 عصر
با سلام خدمت دوستان عید تون مبارک ممکن دستورات استفاده شده در این کد رو شرح دهید :(بیشتر کد اسمبلی منظورم هست )



#include <stdint.h>
#define cmpxchg( ptr, _old, _new ) { \
volatile uint32_t *__ptr = (volatile uint32_t *)(ptr); \
uint32_t __ret; \
asm volatile( "lock; cmpxchgl %2,%1" \
: "=a" (__ret), "+m" (*__ptr) \
: "r" (_new), "0" (_old) \
: "memory"); \
); \
__ret; \
}

pswin.pooya
یک شنبه 03 فروردین 1393, 16:36 عصر
دستور cmpxch برای عوض کردن محتوای دو تا ثبات به صورت اتمیک به کار میره.

کد بالا برای کامپایلر gcc با استفاده از اسمبلی اینلاین مخصوص gnu که ظاهرا کراس پلترفم هست نوشته شده.

homan11
دوشنبه 04 فروردین 1393, 11:59 صبح
سلام استاد عزیز ممنون از جوابتون ، می تونید حوصله بخرج دهید و درمورد این نوع کد زدن بیشتر توصیخ بدهید مثلا کار "=a" و "r" چیه؟در آدرس
http://wiki.osdev.org/Inline_Assembly توضیح داده ولی متاسفانه متوجه نشدم با تشکر

ssbostan
سه شنبه 05 فروردین 1393, 13:39 عصر
باسلام،
یکی از مزایای اسمبلی inline در gcc این هست که کد اسمبلی میتونه با داده های درون برنامه در ارتباط باشه.
یعنی اینکه شما قادر هستید مقدار، آدرس، متغیر و... رو از برنامه به عنوان ورودی کد اسمبلی در نظر بگیرید و خروجی رو در یک متغیر یا آدرس ذخیره کنید.

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


asm("code":outputs:inputs:clobbers);


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

برای اینکه دستور ورودی/خروجی داشته باشه در قسمت کد باید آرگومان ها رو از 0% تا 9% مشخص کنید.

خروجی:
کد میتونه خروجی نداشته باشه. در صورتی که خروجی داشته باشه آرگومان اول یعنی 0% در نظر گرفته میشه.
و اما محدوده چیست؟ همون "a=" و...
شما نسبت به دستوری که دارید استفاده میکنید و قوانین استفاده از اون دستور باید محدوده رو مشخص کنید و این محدوده میتونه:
r: ثبات
m: حافظه
i: مقدار
g: عمومی
و... باشه که این نکته قابل ذکر هست که در مورد خروجی باید قبل از محدوده = هم قرار بدید.

ورودی:
اگر کد خروجی نداشته باشه، ورودی از آرگومان اول یعنی 0% شروع میشه و ورودی های مختلف توسط , از هم جدا میشن.
اما اگر کد خروجی داشته باشه از 1% شروع میشه.
و باز هم محدوده باید مشخص بشه که در بالا تعدادی رو گفتم.

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

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

به طور خلاصه من سعی کردم تمام گزینه هایی که تو ذهنم اومد رو براتون توضیح بدم هرچند نکات بسیار زیادی داره که از حوصله این متن خارج هست.

و اما چند تا مثال خیلی ساده:


asm("mov $10, %0" : "=r" (a));
asm("mov $10, %0" : "=r" (a) : : "ebx");
asm("mov %0, %%eax" : : "m" (a));
asm("mov %1, %0" : "=g" (a) : "i" (10));


کد اول: مقدار 10 رو از طریق ثبات درون متغیر a ذخیره میکنه. خوب خودمون گفتیم از طریق ثبات r و خوده gcc هم ebx رو استفاده میکنه.
کد دوم: مثل کد اول هست با این تفاوت که گفتیم از ebx استفاده نکن.
کد سوم: کد خروجی نداره و مقدار متغیر a که در حافظه هست رو به ثبات eax منتقل میکنه.
کد چهارم: مقدار ورودی که عدد 10 انتخاب کردم رو از طریق ثبات به متغیر a منتقل میکنه که g برای مشخص شدن محدوده توسط خوده gcc استفاده میشه.

موفق باشید.

homan11
چهارشنبه 06 فروردین 1393, 21:19 عصر
دوست عزیز از توضیحات مفید تون بسیار ممنونم امیدوارم در تمام مراحل زندگیتون موفق باشید.