آدرس‌دهی کلمه‌ای
در معماری رایانه، آدرس دهی کلمه‌ای به این معنی است که آدرس‌های حافظه در یک رایانهبه طور منحصر به فرد کلمات حافظه را مشخص می‌کند. معمولاً در مقابل این روش آدرس دهی بایتی استفاده می‌شود، جایی که آدرس‌ها به‌طور منحصر به فرد بایت‌ها را شناسایی می‌کنند. تقریباً تمام معماری‌های رایانه‌ای مدرن از آدرس‌دهی به صورت بایت استفاده می‌کنند و آدرس‌دهی کلمه عمدتاً تنها از منظر تاریخی بررسی می‌شود. رایانه ای که از آدرس دهی کلمه استفاده می‌کند، گاهی اوقات "ماشین کلمه" نامیده می‌شود.
رایانه‌ای را در نظر بگیرید که می‌تواند ۵۲۴،288 (2 ) بیت حافظه را فراهم کند. اگر آن حافظه با استفاده از بایت‌های ۸ بیتی در یک فضای آدرس مسطح آدرس‌دهی بایتی، با استفاده از بایت‌های ۸ بیتی مرتب شده باشد، آنگاه 65536 (2 ) آدرس معتبر، از ۰ تا ۶۵٬۵۳۵ وجود دارد که هر یک نشان‌دهنده ۸ بیت حافظه مستقل است. اگر در عوض در یک فضای آدرس مسطح قابل آدرس دهی کلمه با استفاده از کلمات ۳۲ بیتی مرتب شده باشد، 16384 (2 ) آدرس معتبر از ۰ تا ۱۶۳۸۳ وجود دارد که هر کدام نشان دهنده ۳۲ بیت مستقل است.
به‌طور کلی، حداقل واحد آدرس پذیر در رم (MAU: Minimum Addressable Unit) یک ویژگی خاص از حافظه است. انتزاع‌های مختلف در یک رایانهممکن است از MAUهای متفاوتی استفاده کنند، حتی زمانی که آنها یک حافظه اصلی را نشان می‌دهند. به عنوان مثال، ممکن است یک رایانهبرای مجموعه دستورالعمل‌ها instruction set خود از آدرس‌های ۳۲ بیتی استفاده کند، اما سیستم انسجام حافظه پنهان(cache coherence) CPU ممکن است با حافظه تنها با ریزدانگی(granularity) 64 بایت خطوط کش(cache lines)کار کند، که اجازه می‌دهد هر یک از خطوط کش با تنها یک آدرس ۲۶ بیتی شناسایی شود و سربار حافظه نهان CPU کاهش یابد.
ترجمه آدرس که توسط حافظه مجازی(virtual memory) انجام شده‌است اغلب بر ساختار و عرض فضای آدرس تأثیر می‌گذارد، اما MAU را تغییر نمی‌دهد.
تصمیم برای انتخاب اندازه حداقل واحد آدرس پذیر حافظه می‌تواند می‌تواند سخت باشد. استفاده از یک MAU بزرگتر اجازه می‌دهد تا همان مقدار حافظه را با یک آدرس کوچکتر آدرس دهی شود، که می‌تواند به میزان قابل توجهی نیازهای یک برنامه به حافظه را کاهش دهد. با این حال، استفاده از یک MAU کوچکتر، باعث آسانتر و بهینه تر شدن کار با داده‌های کوچک می‌شود.
فرض کنید برنامه ای می‌خواهد یکی از ۱۲ نشانه سنتی طالع بینی غربی را ذخیره کند. یک علامت واحد را می‌توان در ۴ بیت ذخیره کرد. اگر یک علامت در حداقل واحد آدرس پذیر خود ذخیره شود، اگر از آدرس دهی بایت استفاده شود ۴ بیت استفاده نخواهد شد و ۵۰٪ بازده خواهیم داشت، در حالی که در آدرس دهی کلمه ۳۲ بیتی ۲۸ بیت استفاده نخواهد شد و ۱۲٫۵٪ بازده خواهیم داشت. اگر یک علامت در مینیمم واحد آدرس پذیر MAU با داده‌های دیگر «بسته بندی» شود، آنگاه ممکن است هزینه خواندن و نوشتن در حافظه به نسبت افزایش یابد. برای مثال، برای نوشتن یک علامت جدید در MAU که دادهٔ دیگری نیز در آن بسته‌بندی شده، رایانهابتدا باید مقدار فعلی داخل MAU را خوانده و تنها بیت‌های مناسب را بازنویسی کند و در نهایت مقدار جدید را مجدداً ذخیره کند. در صورتی که برنامه نیاز داشته باشد تا به نخ (thread)های مختلف اجازه دهد تا داده‌های دیگر داخل MAU را به‌طور همزمان تغییر دهد این عملیات بسیار هزینه برخواهد بود.
مثال رایج تر، رشته‌ای از متن است. فرمت‌های رایج برای ذخیره رشته‌ها مانند UTF-8 و ASCII رشته‌ها را به صورت دنباله ای از کد پوینت‌های ۸ بیتی ذخیره می‌کنند. با آدرس دهی به صورت بایت، هر کد می‌تواند در MAU با آدرس دهی مستقل خود بدون هیچ سرباری ذخیره شود. با آدرس دهی کلمه ای ۳۲ بیتی و قرار دادن هر کد پوینت داخل یک MAU جداگانه باعث افزایش استفاده از حافظه به میزان ۳۰۰٪ می‌شود که برای برنامه‌هایی که با رشته‌های بزرگ کار می‌کنند مناسب و قابل اجرا نیست. دسته‌بندی کدهای مجاور درون یک کلمه حافظه باعث جلوگیری از این هزینه می‌شود، هر چند الگوریتم‌های زیادی برای کار با رشته‌ها ترجیح می‌دهند تا بتوانند آدرس‌های مستقل برای کدها در نظر بگیرند. برای اینکه این کار را بتوان با کدهای دسته‌بندی شده انجام داد الگوریتم باید از یک آدرس "wide" یا گسترده یا عریض استفاده کند که همچنین آفست یا محل کاراکتر در کلمه حافظه را مشخص می‌کند. اگر قرار باشد این آدرس گسترده در جایی در حافظه برنامه ذخیره شود ممکن است به حافظه بیشتری نسبت به آدرس‌های معمولی نیاز داشته باشد.
برای ارزیابی تأثیر این روش‌ها در یک برنامه کامل، یک مرورگر را در نظر بگیرید که صفحه ای بزرگ و پیچیده را نمایش می‌دهد. برخی از قسمت‌های حافظه مرورگر برای ذخیره داده‌های ساده مانند عکس‌ها یا متون استفاده می‌شود، مرورگر غالباً می‌خواهد که این داده‌ها به شکل بهینه‌ترین حالت ممکن ذخیره شوند، و در نتیجه تقریباً به همان مقدار داده حافظه اشغال شود بدون اینکه به اندازه MAU توجهی شود. قسمت دیگر حافظه برای ذخیره اشیا مختلف صفحه در مرورگر می‌باشد، و این اشیا شامل تعداد زیادی ارجاع هستند که این ارجاع‌ها می‌توانند به اشیا دیگر صفحه، متون و عکس‌ها و … باشند. مقدار حافظه مورد نیاز برای ذخیره این اشیا بستگی زیادی به عرض آدرس رایانه دارد.
فرض کنید اگر تمام آدرس‌های برنامه ۳۲ بیتی بود، این صفحه وب حدود ۱۰ گیگابایت حافظه اشغال می‌کرد.
بنابر این، آدرس دهی کلمه ای به رایانه اجازه می‌دهد که به‌طور قابل ملاحظه ای میزان بیشتری از حافظه را آدرس دهی کند بدون اینکه عرض آدرس‌ها و درنتیحه آن میزان استفاده متناظر از حافظه افزایش یابد. هر چند این ویژگی تنها در محدوده نسبتاً کوچکی از مجموعه اندازه کاری ارزشمند است و می‌تواند بسته به نرم‌افزار باعث سربارهای قابل توجهی شود. برنامه‌هایی که به‌طور نسبی با کارهای اندکی با داده‌هایی که به صورت بایت هستند مانند عکس، متن، فایل‌ها و ترافیک شبکه انجام می‌دهند می‌توانند بیشترین فایده را داشته باشند.
برنامه ای که روی رایانه در حال اجرا می‌باشد و از آدرس دهی کلمه ای استفاده می‌کند، همچنان می‌تواند با شبیه‌سازی دسترسی به واحدهای کوجک تر، با واحدهای کوچک‌تر حافظه کار کند. برای بارگذاری نیاز داریم کلمه را برداشته و سپس بیت‌های مورد نظر را استخراج کنیم. برای ذخیره نیز نیاز داریم کلمه را بارگذاری کنیم، مقادیر جدید را در آن قرار دهیم و پس از بازنویسی بیت‌های مورد نظر آن را مجدداً در کلمه موجود در حافظه ذخیره کنیم.
فرض کنید چهار کد پوینت متوالی رشته با فرمت UTF-8 را می‌خواهیم در یک کلمه ۳۲ بیتی دسته‌بندی کنیم. اولین کد ممکن است بیت‌های ۰ تا ۷، دومین کد ۸ تا ۱۵، سومین ۱۶–۲۳ و کد چهارم بین‌های ۲۴–۳۱ را اشغال کند. (اگر حافظه قابل آدرس دهی بایت بود، این یک ترتیب بایت انددی است.)
به منظور روشن شدن واضح کد لازم برای دسترسی به زیر کلمه بدون اینکه مثال را خیلی مشابه معماری آدرس دهی کلمه ای خاصی در نظر بگیریم، مثال‌های زیر از اسمبلی MIPS استفاده می‌کنند. در واقعیت MIPS یک معماری آردس دهی بایتی با پشتیبانی مستقیم از بارگذاری و ذخیره‌سازی مقادیر ۸ و ۱۶ بیتی است، اما مثال وانمود می‌کند که تنها از بارگذاری و ذخیره ۳۲-بیتی که در یک کلمه ۳۲ بیتی است باید جدا از یک آدرس ذخیره شود. معماری MIPS انتخاب شده‌است به دلیل اینکه یک زبان اسمبلی ساده و بدون امکانات تخخصی است که باعث راحت تر شدن این عملیات می‌شود.
فرض کنید یک برنامه می‌خواهد سومین کد را در ثبات r1 از کلمه ای داخل آدرسی در ثبات r2 بخواند. با در نظر گرفتن عدم وجود پشتیبانی از مجموعه دستورالعمل‌ها (instruction set)، برنامه باید تمام کلمه را بارگذاری کند، ۱۶ بار شیفت به راست انجام دهد تا دو کد ابتدا را حذف کند و سپس کد چهارم را پنهان کند. اگر آفست به‌طور ایستا (استاتیک) مشخص نباشد، اما در عوض یک بیت-آفست در ثبات r3 ذخیره شده باشد، رویکرد کمی پیچیده‌تر نیاز است. فرض کنید بجای آن برنامه می‌خواهد کد پوینت داخل رجیستر r1 به سومین کد پوینت داخل کلمه در رجیستر r2 قرار دهد. با در نظر گرفتن عدم پشتیبانی از مجموعه دستورالعمل‌ها (instruction set)، برنامه باید تمام کلمه را بارگذاری کند، مقدار قدیمی آن کد پوینت را پنهان کند، مقدار جدید را در محل مورد نظر تغییر دهد و پس از ادغام کردن مقادیر، تمام کلمه را دوباره ذخیره کند. مجدداً، اگر افست به جای آن در ثبات codice_1 ذخیره شود، رویکرد پیچیده تری مورد نیاز است: این دنباله کد فرض می‌کند که یک نخ (thread) دیگر نمی‌تواند بایت‌های دیگر داخل کلمه را همزمان تغییر دهد. اگر تغییرات همزمان ممکن بود، آنگاه ممکن بود یکی از تغییرات صورت نگیرد. برای حل این مشکل، چند دستورالعمل آخر باید به یک حلقه مقایسه-تبدیل تجزیه ناپذیر (atomic) تبدیل شوند تا یک تغییر همزمان به راحتی باعث شود تا عملیات با مقادیر جدید تکرار شود. در این مورد هیج مانعی برای حافظه لازم نیست.
به یک جفت آدرس کلمه و یک آفست درون کلمه آدرس عریض یا گستره (wide - همچنین fat address یا fat pointer) گفته می‌شود. (این را نباید با دیگر کاربردهای آدرس‌های عریض برای ذخیره‌سازی انواع مختلف داده‌های تکمیلی مانند کران‌های یک آرایه اشتباه گرفت) آفست ذخیره شده ممکن است یک بیت-آفست یا بایت-آفست باشد. دنباله کدهای بالا از این مورد که آفست به صورت بیت ذخیره می‌شود سود می‌برند، زیرا از آن به عنوان تعداد شیفت استفاده می‌کنند. یک معماری با پشتیبانی مسقتیم برای انتخاب بایت، ممکن است ترجیح دهد تا فقط یک بایت آفست ذخیره کند.
در این دنباله‌های کد، آفست اضافی باید در کنار آدرس پایه ذخیره شود که در نتیحه آن عملاً نیازهای کلی ذخیره‌سازی آدرس را دو برابر می‌کند. این همیشه در رابطه با ماشین‌های کلمه ای صادق نیست، عمدتاً برای این که خود آدرس‌ها در کنار دیگر داده‌ها بسته‌بندی نمی‌شوند تا دسترسی به آن‌ها کارآمدتر باشد. برای مثال، از کلمات ۶۴ بیتی استفاده می‌کند، اما آدرس‌ها تنها ۳۲ بیت هستند. هنگامی که یک آدرس در حافظه ذخیره می‌شود، در کلمه مربوط به خودش ذخیره می‌شود و در نتیحه آفست بایت می‌تواند در ۳۲ بیت با ارزش تر کلمه قرار گیرد. ناکارآمدی استفاده از آدرس‌های عریض در این سیستم تنها منطق اضافی برای دستکاری این آفست و استخراج و درج بایت‌ها داخل کلمات است و تأثیری در استفاده از حافظه ندارد.
حداقل واحد قابل آدرس دهی در رایانه لزوماً با حداقل اندازه دسترسی به رم در مجموعهٔ دستورالعمل‌های رایانه یکی نیست. برای مثال یک رایانه ممکن است از آدرس دهی بایت بدون اینکه هیچ دستوری برای خواندن و نوشتن روی یک بایت ارائه شود استفاده کند. از برنامه‌ها انتظار می‌رود که آن عملیات را به صورت نرم‌افزاری با تغییر دادن بیت‌ها انجام دهند، مانند دنباله کدهایی که در بالا آورده شد. این کار در رایانه‌ها با معماری ۶۴ بیتی که به عنوان جانشین ابر رایانه‌ها یا مینی رایانه‌های ۳۲ هستند، مانند و نسبتاً رایج است.
استاندارد C بیان می‌کند که از یک اشاره گر انتظار می‌رود که نمایش معمول یک آدرس را در خود داشته باشد. C همپنین به یک اشاره گر اجازه می‌دهد که برای هر شی یا آبجکتی به جز یک فیلد بیت ایجاد شود. این شامل هر هر عنصر مجزا از آرایه ای از بایت‌ها می‌شود. کامپایلرهای سی در رایانه‌هایی که از آدرس دهی کلمه ای استفاده می‌کنند معمولاً از نمایش‌های متفاوتی برای اشاره گرها بسته به اندازه نوع آنها استفاده می‌کنند. یک اشاره گر به یک نوع داده که به اندازه کافی برای قرارگیری در یک کلمه بزرگ است به شکل یک آدرس ساده می‌باشد، در حالی که یک اشاره گر مانند char* یا void* یک آدرس عریض خواهد بود: یک جفت آدرس از یک کلمه و آفست یک بایت داخل آن کلمه؛ بنابراین، تبدیل میان انواع متخلف اشاره گرها عملیات ساده ای نخواهد بود و ممکن است در صورت اشتباه انجام شدن آن، داده‌ها از بین بروند.
به دلیل اینکه اندازه یک struct در سی همواره موقع تصمیم‌گیری برای نمایش یک اشاره گر به آن struct مشخص نیست، نمی‌توان به‌طور قابل اعتمادی قوانین بالا را اعمال کرد. ممکن است کامپایلرها نیاز داشته باشند که محل شروع یک struct را مشخص و تراز کنند تا بتوان از نمایش‌های کارا تری برای اشاره گر استفاده کنند.