اولا بگويم در جدول اسكي من 3 ستون دارد . ستون اول شماره در مبناي 10 . ستون دوم شماره در مبناي 16 و ستون سوم كاراكتر.
و اين كه گفتم كاراكتر 5 شماره اش 35 است از ستون 2 بود يعني در مبناي 16 . كه ستون اولش 53 بود.
حالا ، برنامه:
برنامه زير ، برنامه آماده شده براي چاپ al است. البته بايد al رقم سمت چپش صفر باشد و رقم سمت راستش هم صفر تا 9 باشد.
کد:
.model small
.stack
.code
chaap proc
mov al,08h
mov ah,2h
mov dl,al
add dl,30h
int 21h
mov ah,4ch
int 21h
chaap endp
end chaap
شرح برنامه:
اول در al رقم 08 گذاشته شده.
بعد سرويس تعيين شده(mov ah,2h )
بعد al را در dl گذاشته ايم.
بعد dl را 30h افزوده ايم.(30 در مبناي 16 كه ميشه 3 ضرب در 16 در مبناي 10 )
بعد وقفه را فراخوانده ايم.
نتيجه اجرا :
8
برنامه بعدي برتري اش اينه كه اگر در رقم سمت راست al به جاي صفر تا 9 ، حروف a تا f هم بود مي تواند پوشش دهد.
کد:
.model small
.stack
.code
chaap proc
mov al,0eh
mov ah,2h
mov dl,al
add dl,30h
cmp dl,3ah
jl lable1
add dl,07h
lable1:
int 21h
mov ah,4ch
int 21h
chaap endp
end chaap
شرح برنامه:
اگر به جدول اسكي نگاه كنيد مي فهميد كه چرا باز 7 تا اضافه شده. چون اگر مثلا e بخواهد به شماره مناسب خود برسد به جاي 30 واحد افزايش بايد 37 واحد افزايش يابد. زيرا بين اعداد و حروف در جدول اسكي 7 كاراكتر فاصله انداخته اند. يعني حروف 7 تا رفته اند در جدول پايين.
شرطي در برنامه بالا وجود دارد كه نگاه مي كند ببيند كه dl در چه حدودي است و اگر كوچكتر از آن حد باشد 7 تا اضافه مي كند.
= = = = = = = = = = = = =
برنامه بالا رقم سمت راست al را چاپ كرد ولي رقم سمت چپ al هنوز مانده.
بگذاريد كل برنامه اي كه دو رقم را مي تواند چاپ كند را توضيح بدهم.
اين برنامه اول رقم سمت چپ al را نابود مي كند . يعني صفرش مي كند. پس مي ماند رقم سمت راست . كه برنامه بالايي مي تواند آن را چاپ كند.
بعد يك شيفت به راست(چهار تايي) مي دهد al را تا رقم سمت چپ بنشيند جاي رقم سمت راست. پس باز برنامه بالا مي تواند آن را چاپ كند.
اين شيفت به راست را كمي توضيح مي دهم. مي دانيد كه al داراي 8 بيت است. پس اگر 4 تا هلش بدهيم به راست. 4 بيت نابود مي شود و 4 بيت سمت چپ مي نشيند به جاي 4 بيت سمت راست. و جاي 4 بيت سمت چپ هم صفر مي شود. يك دستور چرخش هم داريم كه هر بيتي بيرون مي رود از آنطرف مي چرخد مي آيد اين طرف مي نشيند انتهاي اين طرف. ولي اين دستور شيفت ، مثل دستور چرخش نيست كه بيتهاي بيرون رفته از آنطرف بچرخند بيايند اين طرف. پس سمت چپ صفر مي شود و سمت چپي ها مي روند جاي سمت راستي ها مي نشينند. مثلا اگر al درونش e3 باشد با اين كار ميشه 0e . مي دانيد كه در 0e ، صفر 4 بيت است و e هم 4 بيت است.
اين از مانور شيفت ولي مانور اول كه براي نگهداشتن سمت راست al است راحت تره. كافيه كه فقط سمت چپ را نابود كنيم. كه با يك and با صفر راحت انجام ميشه.
حالا كل برنامه:
اولا بگم كه من در چاپ al مشكل پيدا كردم و به جاي آن bl قرار دادم. فرقي هم نميكنه ميشه اول al را در bl ريخت و بعد برنامه زير را استفاده كرد.
ميشه برنامه زير را به نام bl_print در برنامه هاي بعدي خودمان استفاده كنيم.
يعني هر موقع خواستيم رجيستري را ببينيم چي داخلشه ، آن را در bl بريزيم و برنامه زير را در قالب يك زيربرنامه احضار كنيم .
كار اصولي تر هم اينه كه اين نوع برنامه ها را جدا كامپايل كنيم و با استفاده از برنامه link هم برنامه در دست اجرا را لينك كنيم و هم برنامه آرشيو خود را و اين طوري از برنامه هاي قبلي خود هم استفاده كنيم. بعدا روش link دو آبجكت را با هم مي گويم.
کد:
.model small
.stack
.code
chaap proc
mov bl,0ech
;----------part 1
mov ah,2h
mov dl,bl
mov cl,04h
shr dl,cl
add dl,30h
cmp dl,3ah
jl lable1
add dl,07h
lable1:
int 21h
; -----------part 2
mov dl,bl
and dl,0fh
add dl,30h
cmp dl,3ah
jl lable2
add dl,07h
lable2:
int 21h
mov ah,4ch
int 21h
chaap endp
end chaap
تقريبا همه قسمتها را قبلا شرح داديم و نياز به شرح ديگه نيست . فقط دو خط زيررا نگاه كنيد:
mov cl,04h
shr dl,cl
اينكه آمده اول در cl عدد 4 را گذاشته و بعد آمده dl را اين مقدار شيفت داده شايد در كامپايلر شما نياز به اين نوع احتياط نباشه و يك دفعه هم بتوانيد به جاي cl همان 4 را بگذاريد.
اول برنامه خط mov bl,0ech به bl مقدار اوليه مي دهد كه همين مقدار بايد چاپ بشه. براي چك برنامه آن را عوض كنيد تا ببينيد درست كار مي كند يا نه.
توجه كنيد كه در ابتداي هر part كه هر part براي چاپ يك نميه bl است ما با دستور mov dl,bl آمده ايم dl را پر كرده ايم.
دستور mov ah,2h كه در part 1 آمده در part 2 هم معتبره. ولي مي توانيد باز هم در part 2 براي احتياط بنويسيد.
در مقايسه part 1 و part 2 بايد بگوييم كه همه قسمتها تقريبا يكي هستند به جز اين كه در يكي and استفاده شده در ديگري shr (بخوانيد شيفت تو رايت) . در مورد اون 0f هم كه در دستور and استفاده شده هم كه مي دونيد يعني چي. يعني 4 بيت صفر و 4 بيت 1 كه باعث ميشه مثل فيلتر قسمت چپ را صفر كند. مي دانيد كه هر عددي با صفر and بشه نتيجه صفر بيرون مي آيد.
اگر يك روز خواستيد مثلا 4 بيت يك رجيستر را يك كنيد مي توانيد با يك آنرا or كنيد.
فكر مي كنم ديگه اين برنامه احتياج به توضيح ندارد.
اين برنامه به نظر من بسيار ضروري است چون باعث ميشه نتايج كارمان را بتوانيم چاپ كنيم.
فعلا كه link دو آبجكت را نگفتيم هم مي توانيم به عنوان يك زير برنامه در برنامه هاي خود استفاده كنيم و مدام ازش استفاده كنيم تا نتايج كارهاي خود را ببينيم.
ولي موقع تبديل اين برنامه به زير برنامه يك نكته مهم را به ياد داشته باشيد. و آن اين كه ((زير برنامه بايد امين باشد.)) و اين برنامه چون dl و cl و .... را دستكاري كرده به درد نمي خوره. پس بهتره اين رجيسترها(و براي احتياط همه رجيسترها را) اول زيربرنامه push كنيد و آخر برنامه pop كنيد.
در مورد چنين زيربرنامه اي مي بينيد كه ورودي خود را از bl گرفته پس با آن بايد متفاوت عمل كرد. سه نوع ورودي گرفتن زيربرنامه را قبلا گفتيم كه اين نوع يك بود كه از رجيستر ورودي مي گرفت.