بافر صفحه كليد و بافرحلقوي
صفحه كليد از طريف وقفه سخت افزاري 9h كنترل ميشود . وقتي كه كليدي فشرده شده يا
رها شود اين وقفه فراخواني خواهد شد.
صفحه كليد هم مانند بسياري از وسايل جانبي مثل ديسك درايو و ... از طريق پورت
مخصوص به خودش با CPU مرتبط ميشود. وقتي كه كليدي فشرده ميشود پردازنده مخصوص
صفحه كليد كه يك تراشه 8048 است كدي موسوم به كد اسكن توليد كرده و در پورت 60h
قرار ميدهد. پس از آن وقفه 9h اين مقدار را از پورت 60h خوانده و در بافر صفحه
كليد قرار ميدهد . با فرصفحه كليد در ناحيه داده هاي بايوس يعني سگمنت شماره 40h
قرار دارد.
بافر حلقوي ----------
بافر صفحه كليد يك ناحيه 16 كلمه اي (32 بايتي ) در ناحيه داده هاي
كاراكتر بعدي از آنجا خوانده خواهد شد . كلمه ديگري بنام Tile هم به موقعيتي
اشاره ميكند كه كاراكتر بعدي كه تايپ ميشود در آن محل قرار ميگيرد.
وقتي يك كاراكتر تايپ ميشود head حركت ميكند و وقتي يك كاراكتر وارد ميشود Tile
يك خانه به جلو ميرود و وقتي هركدام به انتها رسيد به جاي اولش برميگردد. به
شكلي كه هميشه head در تعقيب tile است و وقتي بافر خالي باشد به آندو برهم منطبق
ميشوند . به خاطر اين شكل عملكرد بافر به آن بافرخلقوي ميگوئيم .
دستيابي به ناحيه داده ها و بافر صفحه كليد -----------------------------------------
براي دستيابي به يك سگمنت بايد دو موضوع جديد را ياد بگيريم . يكي تعريف يك
ناحيه بعنوان يك سگمنت و ديگري منطبق كردن يك ناحيه تعريف شده بر يك سگمنت حافظه
براي تعريف يك سگمنت از كلمه Segment استفاده ميكنيم . توجه داريم كه اين تعريف
حتما بايد قبل از code. باشد.
Bios_Data SEGMENT
:
:
Bios_Data Ends
به اين ترتيب يك ناحيه داده اي جديد به اسم Bios_data تعريف كرديم .
براي اينكه اين ناحيه را بر سگمنت 40h يا همان ناحيه داده هاي بايوس منطبق كنيم
راهنماي AT را هم به انتهاي تعريف سگمنت اضافه ميكنيم . Bios_Data SEGMENT AT 40H
:
Bios_Data Ends
حالا در داخل سگمنت تعريفي چند متغير را در آدرسهاي مخصوص تعريف ميكنيم . چون
بايتهاي مربوط به صفحه كليد در آفست 1Ah قرار دارند يك org 1Ah در نظر گرفته و
متغيرها را تعريف ميكنيم .
Bios_Data SEGMENT AT 40H
ORG 100H
HEAD DW ?
TAIL DW ?
BUFFER DW 10 DUP(?)
Bios_Data Ends
org 1ah
به اسمبلر ميگويد كه همه متغيرهائي كه در زير تعريف ميشوند را منطبق
بر آدرس 1ah قرار بدهد . اين كار باعث ميشود كه هميشه متغير head حاوي دوبايت 1ah
و 1bhو باشد.
ون هميشه مقدار آدرسها نسبت به محتواي DS سنجيده ميشوند ( مثلا mov al/[bx] با mov al/ds:[bx]
برابر است ) بايد به اسمبلر بگوئيم كه داده ها در كجا هستند.
براي اين منظور از ASSUME استفاده ميكنيم . به اين صورت
Bios_Data SEGMENT AT 40H
ORG 100H
HEAD DW ?
BUFFER DW 10 DUP(?)
Bios_Data Ends
. CODE
ORG 100H
START:
ASSUME DS:BIOS_DATA
بعد آدرس ناحيه Bios_data را به DS لود ميكنيم . ( با استفاده از رجيستر واسطه ) MOV BX/BIOS_DATA
MOV DS/BX
حال تست ميكنيم كه اگر headو tail برهم منطبق باشند يعني بافر خالي است و
شروع به خواندن كليد ها ميكنيم اما اگر برهم منطبق نباشند محتواي بافر را خوانده
و آن را خالي ميكنيم .
GETCHAR:
MOV BX/HEAD
CMP BX/TAIL
JE GETCHAR
واگر بافر خالي نبود BX محل آخرين كاراكتر داخل بافر را نشان ميدهد . پس محتواي
آن قسمت را خوانده و سپس Tail را هم به همان آدرس تنظيم ميكنيم كه Tailو Headو
بر هم منطبق شوند . ( يعني بافر خالي بشود) MOV DX/[BX]
و ميتوانيم تست كنيم كه اگر كليد خوانده شده Q ( به معني Quit) بود از برنامه
خارج شويم و در غير اينصورت يك كليد ديگر را بخوانيم و در صفحه چاپ كنيم .
آيا كاراكتر Q است ? ; CMP DDL/'Q' JE BYE ;
آيا كاراكتر q است ? ; CMP DL/'q' JE BYE ;
تابع 2 براي خواندن كليد ; .MOV AH/2 ; READ A CHAR
وقفه داس ; INT 21H
پرش به روتين برنامه ; JMP GETCHAR BYE :INT 20H
علاقه مندی ها (Bookmarks)