• 0
kakarot2055

مساعدة في إخراج المتوسط الحسابي لمصفوفة Signed

سؤال

السلام عليكم 

 

عندنا مشروع في الجامعة تسليمه غداً لمادة المايكروبروسيسر 8086 يقوم بإخراج القيمة العظمى والصغرى والمتوسط الحسابي لمصفوفة مخزنة في الذاكرة بداخل البرنامج "ملف الكود" قيمها موجبة وسالبة Signed  وطباعتها 

 

 

الأن انهيت الجزء الخاص ب القيم العظمى والصغرى وامر طباعتهم ولكن واجهت مشكلة في امر المتوسط الحسابي 

; multi-segment executable file template.data segment    ; add your data here!     Array dB 000h,013h,012h,020h,015h,07dh,0FEh,0D7h,055H,0f3h,02Dh,080h,0ffh,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00      MaxI DB "The Maximum Value in Integer = $"     Min1 DB "The Minimum Value in Integer = $"     ten db 10      AVG DB "The Average Value in Integer = $"     endsstack segment    dw   128  dup(0)endscode segmentstart:; set segment registers:    mov ax, data    mov ds, ax    mov es, ax    ; add your code here                   LEA SI,ARRAY ; offset array to si pointer        MOV CL,[si+1] ; size of array        MOV Ch,[si] ; size of array       MOV bL,00 ; initial value of Minimum         XOR AX,AX ; fast way to make Register 0       MOV bH,BYTE PTR[SI] ; initial  value of Maximum   L1:                              CMP bL,BYTE PTR[SI] ; compare Minimum to the value of array      JL L2      MOV bL,BYTE PTR[SI]  ; make bl Minimum with value of si       L2:CMP bH,BYTE PTR[SI]  ;compare Maximum to the value of array      JG L3      MOV bH,BYTE PTR[SI] ;make bl  Maximum with value of si   L3:              mov al,[si]      cwd       Test Al,AljS Nega add DI,ax adc dx,0 Jmp Result  nega:neg ax  sub DI,ax  sbb dx,0   Result:        INC si           loop L1                                       Call  Maximum ; call and Print  Maximum value of the array               TEST bl,BL ;test if bl positive or negative               js  MinimumNN                                               MinimumNN:  call MinimumN  ;  call and Print the  Minimum value and if the value negative go and print negative integer value                    JMP END                                     call Minimum    END:    mov ah,4ch                int 21h             MinimumN PROC    NEAR    ;This Procedure To Convert The Hex Value to decimal values lea dx,Min1 ; Show The Massage  mov ah,9 int 21h xor ax,ax xor dx,dx xor cx,cx      mov al,bl         ; To Make The Result of Negative Value of Minimum correct          NEG AL   ;mov cl,0ahdiv clpush axmov ah,00h div clpush axmov ah,00h div clpush axmov ax,0200h  mov dl,"-"  int 21hpop dxmov dl,dhadd dx,30hint 21hpop dxmov dl,dhadd dx,30hint 21hpop dxmov dl,dhadd dx,30hint 21hmov dl,10int 21hret  MinimumN  ENDP                                Maximum PROC    NEAR         lea dx,MaxI   mov ah,9           ; This Procedure To Convert The Hex Value to decimal values int 21h    xor ax,ax   xor dx,dx   xor cx,cx               mov al,bh    mov cl,0ah  div clpush axand ah,00h   div clpush axand ah,00h   div clpush ax  mov ax,0200h pop dxmov dl,dhadd dx,30hint 21h pop dxmov dl,dhadd dx,30hint 21h pop dxmov dl,dhadd dx,30hint 21h mov dl,10int 21h          mov dl,0dh     mov ah, 2    int 21h       mov dl,0ah     mov ah, 2    int 21hret Maximum ENDP       Minimum PROC    NEAR    ; If The Minimum Value is positive go here and print the result lea dx,Min1mov ah,9int 21hxor ax,ax   xor dx,dx   xor cx,cx           mov al,bl  mov cl,0ahdiv clpush axmov ah,00h div clpush axmov ah,00h div clpush axand ax,0200h  mov dl,"-"  int 21hpop dxmov dl,dhadd dx,30hint 21hpop dxmov dl,dhadd dx,30hint 21hpop dxmov dl,dhadd dx,30hint 21hmov dl,10int 21h           mov dl,0dh     mov ah, 2    int 21h       mov dl,0ah     mov ah, 2    int 21hret  Minimum  ENDP                  average1 PROC    NEAR   xor ax,ax   xor dx,dx           mov aX,dI    mov cl,0ah  div clpush axmov ah,00h   div clpush axmov ah,00h   div clpush ax  mov ax,0200h pop dxmov dl,dhadd dx,30hint 21h pop dxmov dl,dhadd dx,30hint 21h pop dxmov dl,dhadd dx,30hint 21h mov dl,10int 21hret            end start ; set entry point and stop the assembler.

طبعاً  average1 Proc  مازال لم يستخدم بعد قيمة المتوسط الحسابي عندي خاطئة 

 

 

الرجاء المساعدة 

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

10 إجابة على هذا السؤال .

  • 0

الكود متداخل و غير مرتب و لا توجد ملاحظات كافية لفهم أجزائه و لم استطع تنقيحه و إليك بعض الملاحظات التى قد تساعدك فى حل المشكله:

 

1- المتوسط الحسابي هو مجموع العناصر و النتاج يقسم على عدد العناصر.

 

2- لا تستخدم ADC و استخدم ADD فأنت لا تحتاج للـ Carry فى شي و حدوث Overflow أمر طبيعي عند جمع رقم بإشارة مع أخر بدون إشاره و النتيجه ستكون صحيحه، فمثلا:

-13 + 25  = 12F3h + 19h = Ch = 12

3- بعد الإنتهاء من الجمع قم بإستخدام IDIV و لا تستخدم DIV حيث الأولى خاصة بقسمة الأعداد التى قد تحتوى على إشارة و الأخيره للأعداد الموجبة فقط.

 

الأن توجد لديك قيمة المتوسط الحسابي و المشكله ستكون لديك فى طباعته حيث فى حالة كونه سالب ستحتاج لحذف الإشارة عن طريق الضرب فى -1 و ايضا ستحتاج لحفظ طبيعة الإشارة لطباعتها.

 

 

و الله ولي التوفيق

تم تعديل بواسطه C++er
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

لتسهيل تتبع البرنامج الجزء الخاص بعملية إخراج المتوسط الحسابي  اسفل L3

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

............

تم تعديل بواسطه kakarot2055
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

سأفترض أن عنوان المصفوفة موجود داخل SI و حجمها كما قلت موجود داخل CX

   MOV AX, [SI] ; load value of first array element to ax   XOR BX, BX   ; reset bx to use as counterSTART:   INC BX       ; increment bx   CMP BX, CX   ; compare current index with total size   JGE FINISH   ; go to finish if bx greater than or equals to cx   ADD AX, [SI + 2*BX] ; get element at SI + 2*BX (the 2 are size of operand inside array)   JMP START    ; loopFINISH:   XOR DX, DX   ; reset content of DX (explained below)   CMP AX, 0    ; test   JNS UNSIGNED_VAL   MOV DX, -1   ; set dx to -1UNSIGNED_VAL   IDIV CX      ; divide [DX:AX] by CX, store the result back to AX; division work on 32bit number, the hi part is in DX and low part in AX; if AX have sign the we extend it to DX by setting it to -1, otherwise we set DX to 0

الكود من الذاكرة و لم اقم بتجربته و لكن المترض ان يعمل إذا وجدت مشكله ضعها هنا و ستجد الحل إن شاء الله.

 

 

و الله ولي التوفيق

تم تعديل بواسطه C++er
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

للأسف الناتج خاطىء 


 


طبعاً إستبدلت داخل   الكود  كل BX ب DI لأن ريجستر BX مشغولة بالقيم العظمى والصغرى 


 


ولا استطيع عمل LOOP أخرى بسبب أن البرنامج يجب ان يكون فعال ويحتاج زمن قليل 


تم تعديل بواسطه kakarot2055
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

قمت بترجبة الكود و اتضح انى نسيت وضع colon بعد الكلمة UNSIGNED_VAL و غير ذلك وفالكود يعمل جيدا.

 

طبعاً إستبدلت داخل   الكود  كل BX ب DI لأن ريجستر BX مشغولة بالقيم العظمى والصغرى

إذا كان لديك stack يمكنك إستخدام PUSH و POP لحفظ قيم المسجلات و بعد ان تنتهي تقوم بإسترجاع القيمه منهم.

 

إليك النسخه 32بت التى قمت بتجربتها:

#include <cstdio>using namespace std;int main(){	int arr[] = {5, 0, 7, -9, 12, -120};	int* addr = (int*)&arr;   __asm   {      MOV ESI, addr      MOV ECX, 6   }   __asm   {      MOV EAX, [ESI] ; load value of first array element to ax      XOR EDI, EDI   ; reset bx to use as counter   START:      INC EDI       ; increment bx      CMP EDI, ECX   ; compare current index with total size      JGE FINISH   ; go to finish if bx greater than or equals to cx      ADD EAX, [ESI + 4*EDI] ; get element at SI + 2*BX (the 2 are size of operand inside array)      JMP START    ; loop   FINISH:      XOR EDX, EDX   ; reset content of DX (explained below)      CMP EAX, 0    ; test      JNS UNSIGNED_VAL      MOV EDX, -1   UNSIGNED_VAL:      IDIV ECX   }   int res = 0;   __asm   {	   MOV res, EAX   }   printf("%i", res);}

كما ترى البرنامج سيطبع النتيجة بشكل صحيح، قم بتغيير محتويات المصفوفة و راقب عمل البرنامج.

استخدمت مترجم VC++2008SP1.

 

 

و الله ولي التوفيق

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

هناك مشكلة في 

 

 

[SI + 4*DI]

 البرنامج يقول هناك مشكلة في هذا العنوان ؟؟ 

 

وإذا غيرتها ل si  وأصبحت 

[SI + [ 4 * SI]]

فأن هناك قيمة لل AVG ايضاً خاطئة 

 

هذا هو ملف البرنامج إن أحببت ان تلقي عليه نظرة 

 

AbdullaProject.asm

تم تعديل بواسطه kakarot2055
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بعد قراءة الكود علمت انه خطئى، المصفوفة لديك بمساحة واحد بايت للعنصر و ليس 2 بايت و بالتالي السطر:

[SI + 4*DI]

سيصبح

 [SI + DI]

حيث الرقم 4 أو 2 يمثل مساحة العنصر الواحد بالبايت داخل المصفوفة.

 

و الله ولي التوفيق

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

كما قلت أخي الكريم هناك مشكلة في هذا السطر وهو أن برنامج emu8086 لا يقبل هذا الكود يقول هناك خطأ 

(58) [SI] cannot go with [DI] - wrong addressing!
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0
كما قلت أخي الكريم هناك مشكلة في هذا السطر وهو أن برنامج emu8086 لا يقبل هذا الكود يقول هناك خطأ

 

يمكنك إبدال السطر التالي:

      ADD AX, [SI + DI]

بهذا:

      INC SI      ADD AX, [SI]

لاحظ ان هذا السطر سيعمل فقط لأن حجم العنصر داخل المصفوفة 1 بايت، فإن كان 2 إجعله كالتالي:

      ADD SI, 2      ADD AX, [SI]

عموما خبرتي فى برمجة 16بت ضعيفة و كل محولاتي تكون بتحويل الكود من 32بت إلى 16بت مع إجراء التعديلات المناسبة.

 

 

بالنسبة لحل مشكلة المسجلات التى تحتوى على قيمة فانا لاحظت انك فمت بإنشاء stack داخل البرنامج فلماذا لا تقوم بدفع قيم هذه المسجلات داخله و اعادة إستخدامهم ثم ثقوم بإعادة محتواهم فى النهاية؟

 

 

و الله ولي التوفيق

تم تعديل بواسطه C++er
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
زوار
This topic is now closed to further replies.

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .