2015/08/01

أكوادي في أسمبلي 16 بت

السلام عليكم
هذه هي الصفحة المخصصة لـ16 كود أسمبلي 16 بت قمت بكتابتها عند تعلّمي للغة , نبدأ بالوصف ثم الكود:
======================================================
هذا هو كودي الأول ..
برنامج يقوم بطباعة Hello World في حلقة لا نهائية .. وينتظر من المستخدم أن يضغط أي زر في كل دورة للحلقة 
.model small
.stack 100h

.data
msg db "Hello World!",10,13,"$"  ;تعريف متغير يحوي العبارة المطلوبة
;10 ,13 هي محارف نهاية السطر
;$ محرف يدل على نهاية المتغيّر
.code
start: ;دليل يمكننا استعماله للعودة الى هذه النقطة

mov ax,@data ;ax;نحفظ عنوان بداية قسم البيانات في
mov ds,ax  ;data segment;ds;في المسجّل ;ax;نحفظ العنوان الموجود في ;

lea dx,msg ;<==>mov dx,offset msg;dx;وتعني حفظ عنوان المتحول في المسجل

mov ah,9 ;dx;حفظ رقم المفاطعة الخاصة بطباعة النص الموجود عنوانه في
int 21h ;ah;تنفيذ المقاطعة المحفوظة في

mov ah,7;حفظ رقم المقاطعة التي تنتظر حرف من المستخدم
int 21h ;ah;تنفيذ المقاطعة المحفوظة في

jmp start ; قفز إلى الدليل أعلاه
;لن نصل إلى هنا أبدا
mov ax,0c07h;حفظ رقم المقاطعة التي تنهي البرنامج
int 21h ;ah;تنفيذ المقاطعة المحفوظة في

end start; دليل نهاية الملف

======================================================
الكود الثاني :
برنامج يأخذ محرفا من المستخدم .. فإن كان هو الرقم 1 يطبع one وإلا يطبع zero .. ( بمكن تطوير البرنامج لأي عدد من المحارف )
.model small
.stack 100h
.data ;حفظ بعض البيانات
    zer     db 9,"zero",10,"$"
    one     db 9,"one",10,"$"
    ;10; هو رقم الآسكي لنهاية السطر
    ;9;tabهو رقم الآسكي ل;
.code
start:
    mov ax,@data
    mov ds,ax
        
    MOV AH,1;مقاطعة أخذ حرف من المستخدم
    INT 21h

    CMP AL,49;مقارنة الحرف المدخل مع قيمة الآسكي للرقم واحد
    JE ony;اذا كان ناتج المقارنة هو التساوي قم بعملية القفز
;سندخل هنا ان لم تنجح المقارنة
    lea dx,zer;نضع عنوان العبارة 'صفر' في مسجل البيانات
    jmp endy;ونقفز كي لا ننفذ السطر التالي
    ony:
        lea dx,one;نضع عنوان العبارة 'واحد' في مسجل البيانات
    endy:
        mov ah,9;مقاطعة طباعة النص الموجود عنوانه في مسجل البيانات
        int 21h
        
jmp start;العودة لتكرار البرنامج
;لن نصل الى هنا ابدا
mov ax,4c00h
int 21h
end start
======================================================
الكود التالي يقرأ حرف واحد من المستخدم .. ثم يقوم بطباعته .. وينتظر زرا آخر ليخرج
.model small
.stack 100h
.data ;لا يوجد بيانات
.code
start:
    MOV AH,01;مقاطعة أخذ حرف من المستخدم
    INT 21h
    
    MOV DL,AL ;نقل الدخل الى المسجل المستخدم للخرج
    MOV AH,02; تخزين رقم المقاطعة الخاصة بطباعة حرف
    INT 21h

    MOV AH,07h; تخزين رقم المقاطعة الخاصة بإنهاء البرنامج
    INT 21h
    MOV AH,4Ch; تخزين رقم المقاطعة الخاصة بإنهاء البرنامج
    INT 21h
end start
======================================================
وهذا الكود مشابه للسابق .. ولكنه يدخل في حلقة : يطبع كل حرف يدخله المستخدم إلى أن ندخل enter
.model small
.stack 100h
.data ;لا يوجد بيانات
.code
start:
    MOV AH,01;مقاطعة أخذ حرف من المستخدم
    INT 21h

    CMP AL,10;مقارنة مع الآسكي المساوي للانتر
    JE endy;اذا تساوت اقفز الى النهاية
    CMP AL,13;مقارنة مع الآسكي المساوي للانتر
    JE endy;اذا تساوت اقفز الى النهاية
    
;سندخل هنا ان لم تنجح المقارنة
    MOV DL,AL ;نقل الدخل الى المسجل المستخدم للخرج
    MOV AH,02; تخزين رقم المقاطعة الخاصة بطباعة حرف
    INT 21h
jmp start;العودة لتكرار البرنامج
endy:
    MOV AH,4Ch; تخزين رقم المقاطعة الخاصة بإنهاء البرنامج
    INT 21h
end start 
======================================================
الكود الخامس .
البرنامج التالي يأخذ نصّا من المستخدم ويطبعه بشكل معكوس عن طريق تخزينه في المكدس ثم اخراجه :

.model small
.stack 100h
.data
.code
mov ah,01;قيمة مقاطعة أخذ حرف من المستخدم
mov cx,sp;نخزّن قيمة مؤشر المكدس في مسجل العداد
start:
int 21h;تنفيذ مقاطعة قراءة حرف من المستخدم
cmp al,0Dh;هل هو نهاية السطر؟
jle end_
    mov bl,al;نضغ في مسجل آخر لأن الدفع في المكدس يتطلب دفع مسجل 16 بت كاملة
    push bx ;نحفظ الدخل في المكدس
    jmp start
end_:
mov ah,02;تخزين قيمة مقاطعة طباعة حرف
mov dl,0Ah;تخزين قيمة محرف نهاية السطر
int 21h;تنفيذ مقاطعة طباعة الحرف والذي هو نهاية السطر
print:
    cmp cx,sp;طالما لم يصبح مؤشر المكدس كقيمته قبل بدء التخزين
    je end__;اذا اصبح كقيمته القديمة اخرج
    pop dx;أخرج آخر حرف تم تخزينه
    int 21h;ونفذ مقاطعة الطباعة
    jmp print;وكرر العملية
end__:
mov ah,4ch;حفظ قيمة مقاطعة الانهاء
int 21h; تنفيذ مقاطعة الإنهاء
end

_____________________إضافة : __________
لم أستطع منع نفسي من ذكر أن برنامج بلغة BrainF**k للقيام بنفس المهمة هو التالي :
,+[->,+]<[.<]
======================================================
الكود 6 : استخدام طريقة العنونة باستخدام الإزاحة[ disp[bx
;هذا الكود لتوضيح طريقة العنونة التالية
;displacement[bx]
;والتي تشبه الوصول إلى عنصر في مصفوفة
.model small
.stack 100h
.data
    numbers db "ABCDEFGHIJKLMNOPQSTUVWXYZ$";نحفظ الحروف في مقطع البيانات
.code
mov ax,@data;\;نحفظ عنوان مقطع البيانات في مسجل مقطع البيانات
mov ds,ax   ;/

mov ax,0100h;\;مقاطعة قراءة حرف
int 21h     ;/

sub al,30h;تحول الحرف الى رقم
mov ah,0  
mov bx,ax ;نقل الناتج لمسجل القاعدة الذي يُستعمل في العنونة

mov dl,numbers[bx];طريقة العنونة التي تقوم بالوصول للعنصر الذي عنوانه مجموع عنوان المتحول خارج الأقواس مع قيمة المسجل داخل الأقواس
;هو الذي تتم طباعة محتواه في مقاطعة طباعة الحرف;dl;المسجل
;ونضع فيه قيمة أحد الحروف المخزّنة والتي نصل اليها عن طريق عنوان المتحول مضافا اليه إزاحة
mov ax,0200h;مقاطعة طباعة حرف
int 21h

mov ah,4ch;مقاطعة الخروج من البرنامج
int 21h
end
======================================================
 الكود السابع :
الكود التالي يستخدم الإجراءات في عملية ضرب عددين كما أنه ينسّق العملية بشكل مرتب
لاحظ أنه يمكنك فهم الكود من أسماء الاستدعاءات calls دون عناء , ثم تعود إلى كل إجراء بشكل مستقل
مع العلم أنني استخدمت المكدّس لإعادة الناتج , ثم لأخذ الوسطاء في الإجراءات التالية
;هذا الكود يوضّح عملية ضرب رقمين من الدخل وطباعتهما باستخدام العمليات
;Procedures
; ويمكنك قراءته وفهمه بسهولة بسبب القاعدة : فرّق تسد :) إنها السيطرة
.model small
.stack 100h
.data
.code;كل استدعاء يدل على وظيفته من اسمه
    call read_number
    call write_Multiplication_Sign
    call read_number
    call write_Equal_Sign
    call find_Result
    call print_Result
    call End_program
    
read_number proc
    mov ax,0100h;نقوم بمقاطعة الدخل لحرف واحد
    int 21h
    sub al,30h;نحول الحرف الى رقم
    mov ah,00h;نصفّر الجزء العلوي من المسجل حتى يختفظ المسجّل بشكل كامل بالقيمة لنتمكن من دفعه للمكدّس
    pop bx;المكدّس يحتفظ بقيمة مؤشّر التعليمات لذلك يجب أن نحافظ عليه
    push ax;نصع نتيجة الإجراء في المكدّس
    push bx;ونعيد مؤشر التعليمات الى المكدّس
    ret;ونعود إلى التعليمة التي يشير لها مؤشر التعليمات
read_number endp

write_Multiplication_Sign proc
    mov ah,02h;تخزين قيمة مقاطعة الخرج لحرف واحد
    mov dl,2Ah;تخزين قيمة الآسكي لإشارة الجمع
    int 21h;طباعة الحرف المخزّن في المسجل السابق
    ret;العودة لحيث يؤشّر مؤشر التعليمات
write_Multiplication_Sign endp

write_Equal_Sign proc;نفس الإجراء السابق ولكن مع تغيير قيمة الآسكي لتطبع إشارة المساواة
    mov ah,02h
    mov dl,3Dh
    int 21h
    ret
write_Equal_Sign endp

find_Result proc
    pop cx;نحتفظ بمؤشر التعليمات
    pop ax;نأخذ الرقم الأول من المكدّس
    pop bx;نأخذ الرقم الثاني من المكدّس
    push cx;نرجع مؤشر التعليمات
    call multiply_Ax_Bx;نستعدي إجراء ضرب هذين المسجّلين
    ret
find_Result endp

multiply_Ax_Bx proc
    mul bx;سنستخدم الضرب العادي
    ret
multiply_Ax_Bx endp

print_Result proc;ax;يقوم بطباعة النتيجة الموجودة في
    mov cl,0Ah;نخزن الرقم 10
    div cl;على 10;ax;نقسم
    ;حسب آلية عمل تعليمة القسمة;ah;وباقي القسمة في;al;ستخزّن نتيجة القسمة في
    ;al;والعشرات في;ah;الآحاد في;
    mov dx,ax;
    mov ah,02h;نضع قيمة تعليمة طباعة حرف
    
    add dh,30h;نحوّل الآحاد من رقم إلى حرف
    add dl,30h;نحول العشرات من رقم إلى حرف
    
    int 21h;نطبع العشرات
    mov dl,dh;
    int 21h;نطبع الآحاد
    ;dl;الطباعة تتم للقيمة الموجودة في
    ret
print_Result endp

End_Program proc;يقوم بتنفيذ مقاطعة الخروج من البرنامج
    mov ah,4Ch
    int 21h
    ret
End_Program endp
end
======================================================
الكود الثامن . الهدف منه توضيح استخدام الخدمة 2 في المقاطعة 10 .. وهي خدمة نقل مؤشر الكتابة ... بدون مبالغة يمكن باستخدام هذه الخدمة رسم كل أحلامك على الشاشة :) .. الأكواد القادمة ستكون فيها رسومات جميلة :D
.model small
.stack 100h
.data
.code

mov ch,00
mov bl,41
label0:
    mov ah,2h;خدمة نقل المؤشر في المقاطعة 10
    mov dh,ch;نحدد السطر
    mov dl,ch;نحدد العمود
    int 10h;تنفيذ المقاطعة الخاصة بنقل المؤشر

    mov ah,2h;خدمة طباعة حرف في المقاطعة 21
    mov dl,41h;نضع أول حروف الأبجدية في المسجل
    add dl,ch;ونزيد قيمته حسب عداد الحلقة
    int 21h;تنفيذ المقاطعة الخاصة بطباعة الحرف
    
    inc ch;نزيد عداد المؤشر
    cmp ch,30;نقارن هل وصلنا إلى 30
    jne label0;إن لم نصل نقفز عائدين إلى بداية العملية
mov ah,1;خدمة أخذ حرف من المستخدم سنستخدمها للانتظار
int 21h;تنفيذ مقاطعة أخذ الحرف من المستخدم
mov ah,4ch;خدمة إنهاء البرنامج
int 21h;تنفيذ خدمة الإنهاء
end label0
end
======================================================
يا جماعة .. السلام عليكم :)
الكود التالي سيقوم برسم دائرة :) باستخدام تحريك المؤشر (مقاطعة الـBIOS رقم 10 الخدمة 2 )
الفكرة هنا هي في كيفية الاستفادة من db أي تحديد البيانات data التي سنحتاجها في الكود
.model small
.stack 100h
.code
jmp X
;فيما يلي أزواج النقاط أولا السينات ثم العينات _الصادات_تحدد الشكل المطلوب رسمه
;Home Made Circle By Mostafa36a2
db 1,10,1,11,1,12,1,13,1,14,1,15,1,16,1,17,1,18,1,19
db 1,20,2,8,2,9,2,10,2,20,2,21,2,22,3,7,3,8,3,22
db 3,23,4,5,4,6,4,24,4,25,5,4,5,5,5,25,5,26,6,4
db 6,26,7,3,7,27,8,2,8,3,8,27,8,28,9,2,9,28,10,1
db 10,2,10,28,10,29,11,1,11,29,12,1,12,29,13,1,13,29,14,1
db 14,29,15,1,15,29,15,30,16,1,16,29,17,1,17,29,18,1,18,29
db 19,1,19,29,20,1,20,2,20,28,20,29,21,2,21,28,22,2,22,3
db 22,27,22,28,23,3,23,27,24,4,24,26,25,4,25,5,25,25,25,26
db 26,5,26,6,26,24,26,25,27,7,27,8,27,22,27,23,28,8,28,9
db 28,10,28,20,28,21,28,22,29,10,29,11,29,12,29,13,29,14,29,15
db 29,16,29,17,29,18,29,19,29,20
y db 105;متحول يحفظ عدد النقاط
X:
mov bx,@code
mov ds,bx
mov ch,00
mov bx,03
dec bx
label0:
    inc bx
    mov dh,[bx];نحدد السطر
    inc bx
    mov dl,[bx];نحدد العمود
    mov ah,2h;خدمة نقل المؤشر في المقاطعة 10
    int 10h;تنفيذ المقاطعة الخاصة بنقل المؤشر

    mov ah,2h;خدمة طباعة حرف في المقاطعة 21
    mov dl,4Dh;نضع أول حرف آسكي نريد طباعته
    int 21h;تنفيذ المقاطعة الخاصة بطباعة الحرف
    
    inc ch;نزيد عداد المؤشر
    cmp ch,y;قارن هل وصلنا لآخر نقطة
    jne label0;إن لم نصل نقفز عائدين إلى بداية العملية
mov ah,1;خدمة أخذ حرف من المستخدم سنستخدمها للانتظار
int 21h;تنفيذ مقاطعة أخذ الحرف من المستخدم
mov ah,4ch;خدمة إنهاء البرنامج
int 21h;تنفيذ خدمة الإنهاء

end
 ======================================================
 10 - إجراء لطباعة القيمة العددية المحتواة في المسجل ah .. (وهو إجراء هام جدّاً لمن لا يعلم )
.model small
.stack 100h
.data
.code

mov al,0FFh;al;حفظ قيمة ما في
call PrintAL;استدعاء دالة الطباعة
mov ah,4ch;خدمة انهاء البرنامج
int 21h;تنفيذ المقاطعة

PrintAL proc
mov ah,00h
mov bl,0ah
;;;;;;;;;;;;;;;
div bl
push ax;ah;حفظ باقي القسمة وهو موجود داخل
mov ah,00h

div bl
push ax
mov ah,00h

div bl
push ax
;;;;;;;;;;;;;;;;;;;
mov ax,0200h;خدمة طباعة حرف
;;;;;;;;;;;;;;;;;;;
pop dx;نخرج الآحاد
mov dl,dh;تذكر أنها محفوظة في الجزء العلوي ومقاطعة الطباعة تطبع الموجود في الجزء السفلي
add dx,30h;تحويل الرقم إلى حرف
int 21h;طباعة الآحاد

pop dx;نخرج العشرات
mov dl,dh
add dx,30h
int 21h;طباعة العشرات

pop dx;نخرج المئات
mov dl,dh
add dx,30h
int 21h;طباعة المئات

mov dl,10;محرف نهاية السطر
int 21h
;;;;;;;;;;;;;;;
PrintAL endp

end
 ======================================================
 الكود الحادي عشر .. فتح ملف باستخدام الخدمة 3D ثم قراءة عشر بايتات منه باستخدام الخدمة 3F من مقاطعة الدوز رقم 21
.model small
.data
filename db "test.txt",0;انتبه لاسم الملف
;ملاحظة : يجب أن يكون الملف موجوداً في نفس مكان وجود البرنامج
.code

mov dx,@data
mov ds,dx

mov ah,3dh;رقم خدمة فتح الملف
mov al,00h;تحديد نوع فتح الملف للقراءة
mov dx,offset filename;حفظ عنوان اسم الملف في مسجل البيانات
int 21h
;ax;يتم حفظ المقبض في المسجل

mov bx,ax;نقل المقبض إلى مسجل القاعدة
mov ah,3fh;رقم خدمة القراءة من ملف
mov cx,0ah;قراءة عشر بايتات
int 21h;تنفيذ المقاطعة التي ستخزن عشر بايتات في العنوان الذي يشير له مسجل البيانات
;ملاحظة : عندما نستعمل مسجل البيانات فإنه يرتبط بمقطع البيانات
mov ah,9;رقم خدمة طباعة سلسلة موجودة في مسجل البيانات
int 21h;تنفيذ مقاطعة الدوس

mov ah,4ch;رقم خدمة انهاء البرنامج
int 21h;تنفيذ مقاطعة الدوس
end
 ======================================================
الكود الثاني عشر
النسخة المحسنة من الكود 10 (ليست محسنة كثيراً)
البرنامج التالي يحوي إجراء Procedure لطباعة القيمة العشرية للمسجل AX (هام جداً )
يمكن للكسابى نسخ الـprocedure وإضافته لكودهم مباشرة .. وهو يترك cx دون تأثير ويستعمل ax,bx,dx
الفكرة بسيطة جداً القسمة 5 مرات على 10 وحفظ الباقي في المكدس ثم إخراجه وطباعته
.model small
.stack 100h
.data
.code
mov ax,0FFFFh
call PrintAX

mov ah,4ch
int 21h

PrintAX proc
mov dx,0000h
mov bx,0Ah
;;;;;;;;;;;;;;;
div bx
push dx
mov dx,0000h

div bx
push dx
mov dx,0000h

div bx
push dx
mov dx,0000h

div bx
push dx
mov dx,0000h

div bx
push dx
mov dx,0000h
;;;;;;;;;;;;;;;;;;;
mov ax,0200h
;;;;;;;;;;;;;;;;;;;
pop dx
add dx,30h
int 21h

pop dx
add dx,30h
int 21h

pop dx
add dx,30h
int 21h

pop dx
add dx,30h
int 21h

pop dx
add dx,30h
int 21h

mov dl,10
int 21h
;;;;;;;;;;;;;;;
ret
PrintAX endp
end
  ======================================================
الكود الثالث عشر : طباعة القيمة العشرية لمحتوى ax (الكود المحسّن)
يمكنك أخذ الإجراء مباشرة مع العلم أنه لا يؤثر على أي مسجّل بداخله , استعمله وأنت مرتاح
.model small
.stack 100h
.data
.code
mov ax,0FFFFh
call PrintAX
mov ah,4ch
int 21h

PrintAX proc
push ax;حفظ قيم المسجلات في المكدس
push bx
push cx
push dx

mov bx,0Ah;نقسم على 10 لذلك نحفظه في مسجل القاعدة
;;;;;;;;;;;;;;;
mov cx,5;we will loop 5 times
StartDiv:
mov dx,0000h;dx should be zero when deviding
div bx;devide on 10
push dx;حفظ باقي القسمة في المكدس
loop StartDiv

mov ax,0200h;print charachter function number

mov cx,5;we will loop 5 times
StartPop:
pop dx
add dx,30h
int 21h
loop StartPop

mov dl,10
int 21h
;;;;;;;;;;;;;;;
pop dx;استعادة جميع المسجلات المحفوظة بترتيب معاكس للحفظ
pop cx
pop bx
pop ax
ret
PrintAX endp
end
 ======================================================
الكود الرابع عشر
يحتوي إجراء قراءة عدد (يجب أن يكون العدد أقل من 65536 )
الكود التالي يقرأ عدداً ثم يقوم بطباعته باستخدام الإجراء الذي كتبناه سابقاً
;get unsigned short integer
.model small
.stack 100h
.data
.code
call readUSI;;get unsigned short integer
;the result stored in bx
call printEndOfLINE;

mov ax,bx
call printAX;
mov ax,4c00h;الخروج من البرنامج
int 21h;

printEndOfLINE proc
mov ah,02h;
mov dl,0Ah;
int 21h;print end of line
ret
printEndOfLINE endp

readUSI proc

mov bx,0;we will save result in bx
mov cx,0Ah;we will multiply by 10 in every loop cycle
getChar:
mov ah,01;read charachter function
int 21h;now charachter stored in al
cmp al,30h;compare with zero
jl endRead;if we get less than zero
xchg ax,bx;ax=result,bl=character
mul cx;now ax=result*10
mov bh,0;bx=character
sub bx,30h;turn from ascii value to integer value
add ax,bx;ax=result

mov bx,ax;bx=result
jmp getChar
endRead:
ret
readUSI endp

PrintAX proc
push ax;حفظ قيم المسجلات في المكدس
push bx
push cx
push dx

mov bx,0Ah;نقسم على 10 لذلك نحفظه في مسجل القاعدة
;;;;;;;;;;;;;;;
mov cx,5;we will loop 5 times
StartDiv:
mov dx,0000h;dx should be zero when deviding
div bx;devide on 10
push dx;حفظ باقي القسمة في المكدس
loop StartDiv

mov ax,0200h;print charachter function number

mov cx,5;we will loop 5 times
StartPop:
pop dx
add dx,30h
int 21h
loop StartPop

call printEndOfLINE;
;;;;;;;;;;;;;;;
pop dx;استعادة جميع المسجلات المحفوظة بترتيب معاكس للحفظ
pop cx
pop bx
pop ax
ret
PrintAX endp
end
 ======================================================
الكود الخامس عشر
استخدمت الإجراءات الخاصة بالقراءة والطباعة لقراءة عددين من المستخدم وطباعة المجموع
;get unsigned short integer
.model small
.stack 100h
.data
getA_Message db "Please Enter The First  Number   $"
getB_Message db "Please Enter The Second Number   $"
resultIs_Message db "The result is $"
.code
mov ax,@data
mov ds,ax
mov ah,09h;print string function
mov dx,offset getA_Message
int 21h
call readUSI;;read unsigned short integer
push bx;save a

call printEndOfLINE;

mov dx,offset getB_Message
int 21h
call readUSI;;read seconf number
push bx;save b
;the result stored in bx
call printEndOfLINE;

mov dx,offset resultIs_Message
int 21h

pop ax
pop bx
add ax,bx

call printAX;
mov ax,4c00h;الخروج من البرنامج
int 21h;

printEndOfLINE proc
push ax
push dx
mov ah,02h;
mov dl,0Ah;
int 21h;print end of line
pop dx
pop ax
ret
printEndOfLINE endp

readUSI proc;save result in bx
push ax
push cx
push dx
mov bx,0;we will save result in bx
mov cx,0Ah;we will multiply by 10 in every loop cycle
getChar:
mov ah,01;read charachter function
int 21h;now charachter stored in al
cmp al,30h;compare with zero
jl endRead;if we get less than zero
xchg ax,bx;ax=result,bl=character
mul cx;now ax=result*10
mov bh,0;bx=character
sub bx,30h;turn from ascii value to integer value
add ax,bx;ax=result

mov bx,ax;bx=result
jmp getChar
endRead:
pop dx
pop cx
pop ax
ret
readUSI endp

PrintAX proc
push ax;حفظ قيم المسجلات في المكدس
push bx
push cx
push dx

mov bx,0Ah;نقسم على 10 لذلك نحفظه في مسجل القاعدة
;;;;;;;;;;;;;;;
mov cx,5;we will loop 5 times
StartDiv:
mov dx,0000h;dx should be zero when deviding
div bx;devide on 10
push dx;حفظ باقي القسمة في المكدس
loop StartDiv

mov ax,0200h;print charachter function number

mov cx,5;we will loop 5 times
StartPop:
pop dx
add dx,30h
int 21h
loop StartPop

call printEndOfLINE;
;;;;;;;;;;;;;;;
pop dx;استعادة جميع المسجلات المحفوظة بترتيب معاكس للحفظ
pop cx
pop bx
pop ax
ret
PrintAX endp
end
 
 ======================================================
الرابط الأصلي

الكود السادس عشر في الرابط التالي  
;get unsigned short integer
.model small
.stack 100h
.data
getA_Message db "Please Enter The First  Number   $"
getB_Message db "Please Enter The Second Number   $"
getFunction_Message db "Please Enter The Operator (+,-,*,/)    $"
resultIs_Message db 10,13,"The result is    $"

UnknownOperator db "Unknown Operator !!",10,13,'$'
ErrorDivideByZero db "Error , Divide by Zero !!",10,13,'$'
.code
mov ax,@data
mov ds,ax
mov ah,09h;print string function

mov dx,offset getA_Message
int 21h
call readUSI;;read unsigned short integer
push bx;save a

call printEndOfLINE;

mov dx,offset getB_Message
int 21h
call readUSI;;read second number
push bx;save b

call printEndOfLINE;

mov dx,offset getFunction_Message
int 21h
call getOperator;return cl={'*','+','-','/'}={42,43,45,47}

mov dx,offset resultIs_Message
int 21h

pop bx
pop ax
call doOperatorAXClBX;

call printAX;
mov ax,4c00h;الخروج من البرنامج
int 21h;

getOperator proc;return cl={*,+,-,/}
push ax
mov ah,1
int 21h
mov cl,al
pop ax
ret
getOperator endp

doOperatorAXClBX proc;{*,+,-,/}={42,43,45,47}
isSum:
cmp cl,43
jne isMul
add ax,bx
ret
isMul:
cmp cl,42
jne isSub
mul bx
ret
;By Mostafa 0x36a2
isSub:
cmp cl,45
jne isDiv
sub ax,bx
ret
isDiv:
cmp cl,47
jne unKnown
mov dx,00h
cmp bx,0
jne doDiv
mov dx,offset ErrorDivideByZero
mov ah,9
int 21h
ret
doDiv:
div bx
ret
unKnown:
mov dx,offset UnknownOperator
mov ah,9
int 21h
ret
doOperatorAXClBX endp

printEndOfLINE proc
push ax
push dx
mov ah,02h;
mov dl,0Ah;
int 21h;print end of line
pop dx
;arabteam2000
pop ax
ret
printEndOfLINE endp

readUSI proc;save result in bx
push ax
push cx
push dx
mov bx,0;we will save result in bx
mov cx,0Ah;we will multiply by 10 in every loop cycle
getChar:
mov ah,01;read charachter function
int 21h;now charachter stored in al
cmp al,30h;compare with zero
jl endRead;if we get less than zero
xchg ax,bx;ax=result,bl=character
mul cx;now ax=result*10
mov bh,0;bx=character
sub bx,30h;turn from ascii value to integer value
add ax,bx;ax=result

mov bx,ax;bx=result
jmp getChar
endRead:
pop dx
pop cx
pop ax
ret
readUSI endp

PrintAX proc
push ax;حفظ قيم المسجلات في المكدس
push bx
push cx
push dx

mov bx,0Ah;نقسم على 10 لذلك نحفظه في مسجل القاعدة
;;;;;;;;;;;;;;;
mov cx,5;we will loop 5 times
StartDiv:
mov dx,0000h;dx should be zero when deviding
div bx;devide on 10
push dx;حفظ باقي القسمة في المكدس
loop StartDiv

mov ax,0200h;print charachter function number

mov cx,5;we will loop 5 times
StartPop:
pop dx
add dx,30h
int 21h
loop StartPop

call printEndOfLINE;
;;;;;;;;;;;;;;;
pop dx;استعادة جميع المسجلات المحفوظة بترتيب معاكس للحفظ
pop cx
pop bx
pop ax
ret
PrintAX endp
end
 ==================================================
انتهى نقل الأكواد, الأكواد السابقة كتبتها أثناء تعلمي للغة وهي الآن مرجع مفيد لمن يريد البدء بها

ليست هناك تعليقات:

إرسال تعليق