زبان اسمبلی اکس۸۶

زبان اسمبلی x86 خانواده ای از زبان‌های اسمبلی دارای سازگاری عقبرو است که حتی با Intel 2088 که در آوریل ۱۹۷۲ معرفی شد، تا حدودی سازگاری دارد. زبان‌های اسمبلی x86 برای تولید کد هدف برای پردازنده‌های کلاس x86 استفاده می‌شوند. زبان اسمبلی x86 همانند تمام زبان‌های اسمبلی، از یادیارهای کوتاه استفاده می‌کند تا دستورالعمل‌های اساسی را که CPU در یک کامپیوتر می‌تواند درک و دنبال کند، نشان دهد. کامپایلرها گاهی هنگام ترجمهٔ یک برنامه سطح بالا به کد ماشین، کد اسمبلی را به عنوان یک مرحله میانی تولید می‌کنند.
به عنوان یک زبان برنامه‌نویسی، اسمبلی به صورت خاص ماشین و سطح پایین است. زبان‌های اسمبلی به‌طور معمول برای برنامه‌های کاربردی دقیق و زمان بحرانی مورد استفاده قرار می‌گیرند مانند سیستم‌های نهفتهٔ بلادرنگ یا هسته‌های سیستم عامل و درایورهای دستگاه.

تاریخچه

اینتل ۸۰۸۶ و ۸۰۸۸ اولین پردازنده‌هایی بودند که یک مجموعه دستورالعمل داشتند که در حال حاضر معمولاً آن را x86 می‌نامند.
این پردازنده‌های ۱۶ بیتی که تکامل یافتهٔ نسل قبلی پردازنده‌های ۸ بیتی مانند ۸۰۸۰ بودند، ویژگی‌ها و دستورالعمل‌های بسیاری را از آن‌ها به ارث برده و برای نسل ۱۶ بیتی توسعه داده‌اند. ۸۰۸۶ و ۸۰۸۸ هر دو از گذرگاه آدرس ۲۰ بیتی و ثبات‌های داخلی ۱۶ بیتی استفاده می‌کردند؛ اما تفاوت‌هایی نیز داشتند، برای مثال، در حالی که ۸۰۸۶ دارای یک گذرگاه داده ۱۶ بیتی بود، ۸۰۸۸، به عنوان یک گزینهٔ کم هزینه تر برای برنامه‌های کاربردی نهفته و کامپیوترهای کوچک، از یک گذرگاه دادهٔ ۸ بیتی بهره می‌برد.
زبان اسمبلی x86 انواع مختلفی از CPUها را پوشش می‌دهد از جمله: پردازنده‌های اینتلی مانند 80186، 80188، ۸۰۲۸۶، ۸۰۳۸۶، 80486، پنتیوم، پنتیوم پرو و غیره و همچنین پردازنده‌های غیر اینتلی AMD و Cyrix مانند پردازنده‌های 5x86 و K6 و NEC V20 (هرچند این پردازنده‌ها غالباً سازگار با اینتل هستند، دستورالعمل‌هایی را که ممکن است به سختی بخشی از زبان اسمبلی x86 در نظر گرفته شود را به مجموعه دستورالعمل‌های خود اضافه کرده‌اند؛ همانند دستورالعمل‌هایی که Zilog به Z80 اضافه کرد) اصطلاح x86 برای هر پردازنده ای که می‌تواند زبان اسمبلی اصلی را اجرا کند، مورد استفاده قرار می‌گیرد.
مجموعهٔ جدید دستورالعمل‌های x86، یک ابرمجموعه از دستورالعمل‌های ۸۰۸۶ و مجموعه ای از افزونه‌های اضافه شده به این دستورالعمل هاست که از میکروپروسسور اینتل ۸۰۰۸ آغاز شد. سازگاری عقبرو باینری تقریباً کاملی میان تراشهٔ اینتل از ۸۰۸۶ تا نسل فعلی پردازنده‌های x86 وجود دارد، اگر چه برخی از استثنائات وجود دارند. در عمل، استفاده از دستورالعمل‌هایی که روی هر پردازنده ای از اینتل ۸۰۳۸۶ یا پنتیوم به بعد اجرا شود، رایج است. اما در سال‌های اخیر، سیستم عامل‌های مختلف و برنامه‌های کاربردی نرم‌افزار به نیاز به پردازنده‌های مدرن تر پیدا کرده‌اند، پردازنده‌هایی که دست کم از تعدادی از افزونه‌هایی که به مجموعهٔ دستورالعمل‌ها اضافه شده‌اند، پشتیبانی کنند. (به عنوان مثال MMX، 3DNow!، SSE / SSE2 / SSE3).

یادیارها و آپ کد‌ها

هر دستورالعمل مونتاژ x86 با یک یادیار نشان داده می‌شود که اغلب با یک یا چند عملوند ترکیب شده‌است و به یک یا چند بایت به نام آپ کد ترجمه می‌شود؛ به عنوان مثال دستور NOP به 0x90 ترجمه می‌شود و دستور HLT به 0xF4 ترجمه می‌شود. آپ کد‌های بالقوه ای وجود دارند که هیچ یادیار مستندی برای آن‌ها وجود ندارد. پردازنده‌های مختلف ممکن است این آپ کد‌ها را به‌طور متفاوتی از یکدیگر تفسیر کنند، برنامه ای که با استفاده از آن‌ها ایجاد شود، متناقض رفتار خواهد کرد یا حتی در برخی از پردازنده‌ها یک استثنا ایجاد می‌کند. این آپ کد‌ها اغلب در مسابقه‌های کدنویسی به عنوان راهی برای کوچکتر، سریع تر و ظریف تر کردن کد استفاده می‌شوند یا تنها نشان دهندهٔ مهارت کدنویس می‌باشند.

جابجایی بین حالت‌ها

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

دستورالعمل‌های پشته

معماری x86 دارای پشتیبانی سخت‌افزاری برای اجرای مکانیسم‌های مربوط به پشته است. دستورالعمل‌هایی مانند push، pop، call و ret با کمک پشته اجرا می‌شوند و برای پاس دادن پارامترها، اختصاص دادن فضا به داده‌های محلی و ذخیره و بازیابی نقاط بازگشت دستور call استفاده می‌شود. دستورالعمل ret size وقتی به کار می‌رود که تابع صدا زده شده مسئولیت احیای فضای اشغال شدهٔ پشته توسط پارامترها را به عهده داشته باشد.
برای تنظیم یک کادر پشته جهت نگهداری داده‌های محلی یک تابع بازگشتی چندین راه وجود دارد؛ اولین راه استفاده از دستورالعمل enter (این دستور همراه با ۸۰۳۸۶ معرفی شد) است که می‌تواند سریعتر از بسیاری دستورالعمل‌های دیگر باشد (مانند push bp ؛ mov bp,sp ؛ sub sp,size). هرچند سریع تر بودن یا آهسته‌تر بودن این روش علاوه بر نوع پیاده‌سازی پردازندهٔ x86، وابسته به قراردادهای فراخوانی مربوط به کامپایلر، برنامه‌نویس یا کد خاص یک برنامه نیز خواهد بود.
طیف گستردهٔ حالت‌های آدرس دهی (از جمله بی واسطه و پایه + افست) برای دستورالعمل‌هایی مانند push و pop، استفادهٔ مستقیم از پشته را برای داده‌هایی مانند عدد صحیح، ممیز شناور و آدرس ساده‌تر می‌کند، همچنین، نگه داشتن مشخصات و مکانیزم ABI نسبت به برخی معماری‌های RISC ساده‌تر خواهد بود.

دستورالعمل‌های مربوط به اعداد صحیح در ALU

اسمبلی x86 دارای عملیات‌های ریاضی استاندارد، مانند: add، sub، mul، idiv عملگرهای منطقی مانندand or: xor، neg ؛ عملیات شیفت ریاضی و منطقی: sal / sar، shl / shr ؛ چرخش همراه با رقم نقلی و چرخش بدون رقم نقلی مانند: rcl / rcr rol / ror، مکمل دستورالعمل‌های محاسبهٔ BCD , aaa، aad، daa و سایر دستورالعمل‌ها است.

دستورالعمل‌های ممیز شناور

زبان اسمبلی x86 شامل دستورالعمل‌هایی برای یک واحد ممیز شناور مبتنی بر پشته (FPU) است. FPU در سری پردازنده‌های ۸۰۸۶ تا ۸۰۳۸۶، یک پردازندهٔ جداگانهٔ کمکی اختیاری بود، در سری پردازنده‌های ۸۰۴۸۶ یک ویژگی اختیاری روی تراشه بود و از سری ۸۰۴۸۶ به بعد، یک ویژگی استاندارد در هر پردازنده Intel x86 است، که از پنتیوم آغاز شد. دستورالعمل‌های FPU شامل جمع، تفریق، نفی، ضرب، تقسیم، باقی مانده، ریشه‌های مربع، کوتاه سازی عدد صحیح، کوتاه سازی کسر و مقیاس کردن با توان دو است. این دستوالعمل‌ها همچنین شامل دستورالعمل‌های تبدیل هستند که می‌توانند یک مقدار را از حافظه در هر یک از فرمت‌های: دهدهی کدگذاری شده به صورت دودویی، صحیح ۳۲ بیتی، صحیح ۶۴ بیتی، ممیز شناور ۳۲ بیتی، ممیز شناور ۶۴ بیتی یا ممیز شناور ۸۰ بیتی (در هنگام بارگیری، مقدار مورد نظر به حالت ممیز شناور در حال حاضر استفاده شده تبدیل می‌شود) بارگذاری یا در حافظه ذخیره کنند. x86 همچنین شامل تعدادی از توابع غیرجبری، از جمله سینوس، کسینوس، تانژانت، آرکتانژانت، به توان رساندن با پایه ۲ و لگاریتم در مبنای‌های ۲، ۱۰، یا e، می‌شود.
دستورالعمل‌هایی که مربوط به ثبات‌های پشته هستند معمولاً فرمتی به شکلfop st,st(n) یا fop st(n),st دارند که st معادل st(0) می‌باشد و st(n) یکی از ۸ رکورد پشته (st(0)، st(1)، …، st(7)). مانند دستورالعمل‌های مربوط به اعداد صحیح، اولین عملوند هم اولین عملوند مبدأ است و هم عملوند مقصد. fsubr و fdivr باید قبل از انجام تفریق یا تقسیم، اولی مبادله اپراتورهای منبع را انتخاب کنند. دستورالعمل اضافه، تفریق، ضرب، تقسیم، ذخیره و مقایسه شامل دستورالعمل‌هایی است که بعد از عملیاتشان پشته بالای پشته می‌شوند؛ بنابراین، به عنوان مثال، faddp st(1), st محاسبه st(1) = st(1) + st(0)، سپس st(0) از بالای پشته حذف می‌کند، بنابراین نتیجه در st(1) بالای پشته در st(0) .

دستورالعمل SIMD

CPUهای مدرن x86 شامل دستورالعمل‌های SIMD هستند که عمدتاً عملیات مشابه را به‌طور موازی در بسیاری از مقادیر کد گذاری شده در ثبت یک SIMD گسترده انجام می‌دهند. تکنولوژی‌های مختلف آموزش از عملیات‌های مختلف در مجموعه‌های ثبت نام مختلف پشتیبانی می‌کنند اما در کل کامل (از MMX به SSE4.2) شامل محاسبات عمومی در ریاضی عدد صحیح یا شناور (اضافه کردن، تفریق، ضرب، تغییر، حداقل، حداکثر سازی، مقایسه، تقسیم یا مربع ریشه) بنابراین برای مثال، paddw mm0, mm1 انجام ۴ موازی ۱۶ بیتی (نشان داده شده w) عدد صحیح می‌افزاید (نشان داده شده padd) از mm0 ارزش به mm1 و در نتیجه در ذخیره mm0 . جریان SIMD Extensions یا SSE همچنین شامل یک حالت نقطه شناور است که در آن فقط تنها اولین مقدار از registers در واقع اصلاح شده‌است (گسترش در SSE2). برخی از دستورالعمل‌های غیرمعمول دیگر شامل مجموع اختلاف‌های مطلق (استفاده می‌شود برای برآورد حرکت در فشرده سازی ویدئو، مانند در MPEG انجام می‌شود) و دستورالعمل تجمع ۱۶ بیتی (مفید برای نرم‌افزار مبتنی بر ترکیب آلفا و فیلتر دیجیتال). SSE (از SSE3) و 3DNow! برنامه‌های افزودنی شامل دستورالعمل اضافه کردن و تفریق برای درمان مقادیر ذره شناور زوج مانند اعداد پیچیده‌است.
این مجموعه دستورالعمل‌ها همچنین شامل دستورالعمل‌های چند کلمه ای ثابت متعدد برای شیفت دادن، قرار دادن و استخراج مقادیر درون ثبات‌ها هستند. علاوه بر این دستورالعمل‌هایی برای انتقال داده بین ثبات‌های عدد صحیح و ثبات‌های XMM (مورد استفاده در SSE) FPU (استفاده شده در MMX)

دستورالعمل‌های دستکاری اطلاعات

پردازندهٔ x86 همچنین شامل حالت‌های پیچیدهٔ آدرس دهی حافظه با یک افست بی واسطه، یک ثبات، یک ثبات با یک افست، یک ثبات مقیاس پذیر با افست یا بدون افست، و یک ثبات با یک افست اختیاری و یک ثبات مقیاس پذیر؛ بنابراین، برای مثال، می‌توان mov eax, [Table + ebx + esi*4] را به عنوان یک دستور واحد که ۳۲ بیت داده را از آدرس محاسبه شده با افست (Table + ebx + esi * 4) از ds بارگذاری می‌کند و در ثبات eax ذخیره می‌کند. به‌طور کلی، پردازنده‌های x86 می‌توانند بارگذاری کرده و استفاده از حافظه سازگار با اندازه هر یک از ثبت نام آن عمل می‌کند. (دستورالعمل SIMD همچنین شامل دستورالعمل نیمه بار است)
مجموعه آموزشی x86 شامل بار رشته، فروشگاه، حرکت، اسکن و مقایسه دستورالعمل (lods، stos، movs، scas و cmps) که انجام هر عملیات به یک اندازه مشخص (b برای بایت ۸ بیتی، w برای کلمه ۱۶ بیتی، d برای کلمهٔ ۳۲ بیتی دو برابر) پس از آن افزایش / کم می (بسته به DF، پرچم جهت) آدرس ثبت نام ضمنی (si برای lods، di برای stos و scas، و هر دو برای movs و cmps). برای بار، فروشگاه و عملیات اسکن، ضمنی هدف / منبع / مقایسه ثبت نام در است al، ax یا eax ثبت نام (بسته به اندازه). ثبات بخش ضمنی استفاده می‌شود ds برای si و es برای di . ثبت نام cx یا ecx به عنوان یک شمارنده کاهش می‌یابد و عملیات زمانی که شمارنده برابر صفر می‌شود یا (برای اسکن و مقایسه‌ها) هنگامی که نابرابری شناسایی می‌شود، متوقف می‌شود.
پشته با اشاره گر پشته ضمنی کاهش (افزایش) و افزایش (پاپ) قرار می‌گیرد. در حالت ۱۶ بیتی، این نشانگر پشته ضمنی به عنوان SS: [SP] خطاب شده‌است، در حالت ۳۲ بیت SS است: [ESP]، و در حالت ۶۴ بیتی [RSP] است. اشاره گر پشته عموماً به آخرین مقدار ذخیره شده اشاره می‌کند، با این فرض که اندازه آن با حالت عملیاتی پردازنده (یعنی ۱۶، ۳۲ یا ۶۴ بیت) مطابقت دارد با عرض پیش فرض push / pop / call / ret دستورالعمل. همچنین دستورالعمل‌ها enter و leave که ذخیره و حذف داده‌ها از بالای پشته در هنگام تنظیم یک اشاره گر قاب پشته در bp / ebp / rbp . با این حال، تنظیم مستقیم، یا جمع و تفریق به ثبت sp / esp / rsp نیز پشتیبانی می‌شود، بنابراین دستورالعمل enter / leave به‌طور کلی غیر ضروری است.

این کد در آغاز یک تابع نوشته می‌شود: 
 push    ebp       ; save calling function's stack frame (ebp)
 mov     ebp, esp  ; make a new stack frame on top of our caller's stack
 sub     esp, 4    ; allocate 4 bytes of stack space for this function's local variables
 … که به لحاظ عملکردی برابر است با: 
 enter   4, 0
 دستورالعمل‌های دیگر برای دستکاری پشته شامل pushf / popf برای ذخیره و بازیابی (E) FLAGS، دستورالعمل pusha / popa برای ذخیره و بازیابی تمامی ثبات‌های صحیح در پشته، می‌باشد.
فرض بر این است که ارزش برای یک بار یا فروشگاه SIMD در موقعیت‌های مجاور برای ثبت SIMD بسته‌بندی می‌شود و آن‌ها را در ترتیبی از ترتیب کمی محدود می‌کند. بعضی از دستورالعمل‌های بارگذاری و ذخیره SSE به درستی عمل می‌کنند تا هماهنگ سازی ۱۶ بایت انجام شود. دستورالعمل‌های SIMD همچنین شامل دستورالعمل پیشفرشی هستند که بار را انجام می‌دهند اما هیچ ثبتی را هدف قرار نمی‌دهند، که برای بارگیری کش استفاده می‌شود. دستورالعمل‌های SSE همچنین شامل دستورالعمل‌های فروشگاه غیر زمانی هستند که فروشگاه‌ها را مستقیماً به حافظه بدون انجام کش کش اختصاص می‌دهند اگر مقصد قبلاً ذخیره نگردد (در غیر این صورت مانند یک فروشگاه منظم رفتار خواهد کرد)
بیشترین دستورالعمل عدد صحیح عمومی و شناور (اما بدون SIMD) می‌تواند از یک پارامتر به عنوان یک منبع پیچیده به عنوان پارامتر منبع دوم استفاده کند. دستورالعمل‌های عدد صحیح نیز می‌توانند یک پارامتر حافظه را به عنوان یک عملگر مقصد اعمال کنند.
مأموریت x86 دارای عملیات پرش بدون قید و شرط، <code id="mwAbs">jmp</code> که می‌تواند یک آدرس فوری، یک ثبت یا یک آدرس غیرمستقیم به عنوان یک پارامتر (توجه داشته باشید که اکثر پردازنده‌های RISC فقط از یک پرونده لینک یا یک جابجایی فوری کوتاه برای پریدن حمایت می‌کنند).
همچنین پشتیبانی می‌شود چند جهش مشروط، از جمله jz (پرش به صفر)، jnz (پرش در غیر صفر)، jg (پرش در بزرگتر از، امضا)، jl (پرش در کمتر از، امضا)، ja (پرش در بالا / بزرگتر از، بدون علامت)، jb (پرش در زیر / کمتر از، unsigned). این عملیات مشروط بر اساس بیت مشخص در ثبت (E) FLAGS بنا شده‌است. بسیاری از عملیات ریاضی و منطقی، بسته به نتیجه آنها، این پرچم‌ها را مشخص یا تکمیل می‌کنند. مقایسه مقادیر cmp (مقایسه) و دستورالعمل‌های <code id="mwAcY">test</code>، پرچم‌ها را به گونه ای تنظیم می‌کند که به ترتیب، آن‌ها را به‌طور جداگانه یا عملیات bitwise AND انجام داده‌اند، بدون تغییر مقادیر عملان. همچنین دستورالعمل‌هایی مانند clc (پرچم حمل روشن) و cmc (پرچم تکمیل حمل) وجود دارد که به‌طور مستقیم بر روی پرچم‌ها کار می‌کند. شناور مقایسه نقاط از طریق انجام fcom یا ficom دستورالعمل که در نهایت باید به پرچم عدد صحیح تبدیل می‌شود.
هر عمل پرش به سه شکل متفاوت است: بسته به اندازه اپنج. پرش کوتاه از عملیات امضا شده ۸ بیتی استفاده می‌کند که از دستورالعمل فعلی جبران می‌شود. پرش نزدیک شبیه یک پرش کوتاه است اما با استفاده از عملگر ۱۶ بیتی امضا شده (در حالت واقعی یا محافظت شده) یا عمل ۳۲ بیتی امضا شده (فقط در حالت محافظت شده ۳۲ بیتی). پرش به مراتب یکی است که از پایه کامل بخش استفاده می‌کند: مقدار افست به عنوان آدرس مطلق. اشکال غیرمستقیم و نمایه شده از هر کدام نیز وجود دارد.
علاوه بر عملیات پرش ساده، call (call subroutine) و ret (return from subroutine) دستورالعمل‌ها هستند. قبل از انتقال کنترل به زیر فرعی، call را فشار دهید آدرس offset بخش دستورالعمل زیر call به پشته؛ ret این مقدار را از پشته باز می‌کند و به آن می‌پیوندد، به‌طور مؤثر بازگشت جریان کنترل به آن قسمت از برنامه. در مورد far call، پایه بخش تحت فشار قرار می‌گیرد؛ far ret می‌آید افست و سپس پایه بخش به بازگشت.
همچنین دو دستورالعمل مشابه وجود دارد: <code id="mwAdk">int</code> (interrupt)، که موجب صرفه جویی در مقدار فعلی (E) FLAGS ثبت شده در پشته می‌شود، سپس یک far call انجام می‌دهد، به جز آن که به جای آدرس، از یک بردار وقفه، یک شاخص به یک جدول استفاده می‌کند از آدرس‌های پردازش وقفه. به‌طور معمول، پردازنده وقفه موجب صرفه جویی در تمام سایر پردازنده‌های ثبت شده مورد استفاده می‌شود، مگر اینکه آن‌ها برای بازگشت نتیجه عملیات به برنامه تماس (در نرم‌افزار به نام وقفه‌ها) مورد استفاده قرار گیرد. بازگشت تطبیقی از دستورالعمل وقفه iret، که پس از بازگشت، پرچم‌ها را بازیابی می‌کند. قطعهای نرم از نوع توصیف شده در بالا بعضی از سیستم عامل‌ها برای تماس‌های سیستم استفاده می‌شود و همچنین می‌تواند در اشکال زدایی مدرسان وقفه‌های سخت استفاده شود. وقفه‌های سخت باعث وقایع سخت‌افزاری خارجی می‌شوند و باید تمام مقادیر ثبت را حفظ کنند به عنوان وضعیت برنامه فعلی اجرای ناشناخته است. در حالت حفاظت شده، وقفه ممکن است توسط سیستم عامل برای راه اندازی یک سوئیچ کار، که به‌طور خودکار تمام ثبت نام از کار فعال را ذخیره کنید.

برنامهٔ "سلام دنیا!" برای DOS در اسمبلی به سبک MASM

از وقفهٔ 21h برای نمایش خروجی استفاده می‌شود، مثال‌های دیگر از printf برای نمایش خروجی استفاده می‌کنند . 
.model small.stack 100h.datamsg db 'Hello world!$'.codestart:mov ah, 09h   ; Display the messagelea dx, msgint 21hmov ax, 4C00h  ; Terminate the executableint 21hend start

برنامهٔ "سلام دنیا!" برای ویندوز در اسمبلی به سبک MASM

; requires /coff switch on 6.15 and earlier versions.386.model small,c.stack 1000h.datamsg     db "Hello world!",0.codeincludelib libcmt.libincludelib libvcruntime.libincludelib libucrt.libincludelib legacy_stdio_definitions.libextrn printf:nearextrn exit:nearpublic mainmain proc
        push    offset msg
        call    printf
        push    0
        call    exitmain endpend

برنامهٔ "سلام دنیا!" برای ویندوز در اسمبلی به سبک NASM

; Image base = 0x00400000%define RVA(x) (x-0x00400000)section .textpush dword hellocall dword [printf]push byte +0call dword [exit]retsection .datahello db "Hello world!"section .idatadd RVA(msvcrt_LookupTable)dd -1dd 0dd RVA(msvcrt_string)dd RVA(msvcrt_imports)times 5 dd 0 ; جدول را تمام می‌کندmsvcrt_string dd "msvcrt.dll", 0msvcrt_LookupTable:dd RVA(msvcrt_printf)dd RVA(msvcrt_exit)dd 0msvcrt_imports:printf dd RVA(msvcrt_printf)exit dd RVA(msvcrt_exit)dd 0msvcrt_printf:dw 1dw "printf", 0msvcrt_exit:dw 2dw "exit", 0dd 0

برنامهٔ "سلام دنیا!" برای لینوکس در اسمبلی به سبک NASM

;; This program runs in 32-bit protected mode.;  build: nasm -f elf -F stabs name.asm;  link:  ld -o name name.o;; In 64-bit long mode you can use 64-bit registers (e.g. rax instead of eax, rbx instead of ebx, etc.); Also change "-f elf " for "-f elf64" in build command.;section .data                           ; section for initialized datastr:     db 'Hello world!', 0Ah         ; message string with new-line char at the end (10 decimal)str_len: equ $ - str                    ; calcs length of string (bytes) by subtracting the str's start address
                                            ; from this address ($ symbol)section .text                           ; this is the code sectionglobal _start                           ; _start is the entry point and needs global scope to be 'seen' by the
                                            ; linker --equivalent to main() in C/C++_start:                                 ; definition of _start procedure begins heremov eax, 4                   ; specify the sys_write function code (from OS vector table)mov ebx, 1                   ; specify file descriptor stdout --in gnu/linux, everything's treated as a file,
                                             ; even hardware devicesmov ecx, str                 ; move start _address_ of string message to ecx registermov edx, str_len             ; move length of message (in bytes)int 80h                      ; interrupt kernel to perform the system call we just set up -
                                             ; in gnu/linux services are requested through the kernelmov eax, 1                   ; specify sys_exit function code (from OS vector table)mov ebx, 0                   ; specify return code for OS (zero tells OS everything went fine)int 80h                      ; interrupt kernel to perform system call (to exit)

برنامهٔ "سلام دنیا!" برای لینوکس در اسمبلی به سبک NASM با استفاده از کتابخانه استاندارد C

;;  This program runs in 32-bit protected mode.;  gcc links the standard-C library by default;  build: nasm -f elf -F stabs name.asm;  link:  gcc -o name name.o;; In 64-bit long mode you can use 64-bit registers (e.g. rax instead of eax, rbx instead of ebx, etc..); Also change "-f elf " for "-f elf64" in build command.;
        global  main                                ;main must be defined as it being compiled against the C-Standard Library
        extern  printf                               ;declares use of external symbol as printf is declared in a different object-module.
                                                           ;Linker resolves this symbol later.segment .data                                       ;section for initialized datastring db 'Hello world!', 0Ah, 0h           ;message string with new-line char (10 decimal) and the NULL terminator
                                                    ;string now refers to the starting address at which 'Hello, World' is stored.segment .textmain:
        push    string                              ;push the address of first character of string onto stack. This will be argument to printf
        call    printf                              ;calls printf
        add     esp, 4                              ;advances stack-pointer by 4 flushing out the pushed string argument
        ret                                         ;return

برنامهٔ "سلام دنیا!" برای لینوکس ۶۴ بیتی در اسمبلی به سبک NASM

;  build: nasm -f elf64 -F stabs name.asm;  link:  ld -o name name.oBITS 64SECTION .dataHello:  db "Hello world!",10len_Hello: equ $-HelloSECTION .textglobal _start_start:mov rax,1   ; write syscall (x86_64)mov rdi,1   ; fd = stdoutmov rsi,Hello  ; *buf = Hellomov rdx,len_Hello ; count = len_Hellosyscallmov rax,60   ; exit syscall (x86_64)mov rdi,0   ; status = 0 (exit normally)syscall

استفاده از ثبات‌های پرچم

پرچم‌ها در معماری x86 برای عمل مقایسه بسیار مورد استفاده قرار می‌گیرند. هنگام مقایسهٔ بین دو داده، CPU، مقدار پرچم یا پرچم مربوطه را تنظیم می‌کند. با توجه به مقادیر قرار گرفته در پرچم‌ها، دستورالعمل‌های پرش شرطی انجام می‌شوند و برنامه به کدی که باید انجام شود پرش می‌کند، به عنوان مثال: 
cmp eax, ebxjne do_something; ...do_something:; do something here
 پرچم‌ها نیز در معماری x86 برای روشن و خاموش کردن ویژگی‌های خاص یا حالت‌های اجرا استفاده می‌شود. برای مثال، برای غیرفعال کردن همه وقفه‌های ماسک، می‌توانید از دستور زیر استفاده کنید: 
cli
 ثبت نام پرچم‌ها نیز می‌تواند به‌طور مستقیم مشاهده شود. کم ۸ بیت از ثبت نام پرچم را می‌توان با استفاده از دستور lahf به ah lahf . کل ثبت نام پرچم‌ها همچنین می‌تواند با استفاده از دستورالعمل pushf، popf، int (از جمله into) و iret .
اشارهگر دستور ip در حالت ۱۶ بیت نامیده می‌شود، در حالت ۳۲ بیتی eip در حالت ۶۴ بیتی rip شود. ثبت نام اشارهگر دستور اشاره به آدرس حافظه است که پردازنده بعدی تلاش برای اجرا؛ آن را نمی‌توان به صورت مستقیم در حالت ۱۶ بیتی یا ۳۲ بیتی مشاهده کرد، اما یک توالی مانند زیر می‌توان برای قرار دادن آدرس next_line به eax : 
call next_linenext_line:pop eax
 این دنبالهٔ دستورالعمل‌ها، کد مستقل موقعیتی را ایجاد می‌کند، زیرا call یک دستور promoter-relative prompt را به دست می‌دهد که صفر را در بایت دستورالعمل هدف از دستورالعمل بعدی (در این مورد ۰) توصیف می‌کند.
نوشتن به اشاره گر دستورالعمل ساده است - دستور jmp دستورالعمل دستورالعمل را به آدرس مقصد هدایت می‌کند، به عنوان مثال، یک توالی مانند زیر، محتویات eax را به eip : 
jmp eax
 در حالت ۶۴ بیتی، دستورالعمل‌ها خود می‌توانند داده‌های مربوط به اشاره گر دستورالعمل را ارجاع دهند، بنابراین دیگر کمتر نیاز به کپی کردن مقدار IP در یک رجیستر دیگر، خواهیم داشت.