الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

حساب المعدل واستخدام call method

بدأه A33 في 27 مايو 2010 · 12 رد · 1,949 مشاهدة · في أرشيف قسم الـــ Assembly
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاااته ..

السؤااال هو أن نجعل المستخدم يدخل 3 أرقم ..

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

وإذا لا ....يحسب معدل هذه الأرقاام

هذه محاااولتي .....بس في خطأ ؟؟

أتمنى مسااااااااااااااااااااااااااااااعدتكم يا أخواااااااااااااني لأني مبتدأه في الأسمبلي .. ونستخدم برنامج pcspim

.data
string_1:.asciiz"calculate the average of three numbers :\n"
string_2:.asciiz"Enter the first number:\n"
string_3:.asciiz"Enter the second number:\n"
string_4:.asciiz"Enter the THIRD number :\n"
string_5:.asciiz"the average number is :\n"
string_6:.asciiz"please change your input :\n"

.text


main:

la $a0,string_1
li $v0,4
syscall



la $a0,string_2
li $v0,4
syscall

#get the first number from the user and place it in $t0
li $v0, 5 #load syscall read_int into v0
syscall #call the system
move $t0, $v0 # move the content of v0, which is the first number to t0

 la $a0,string_3 
 li $v0,4
 syscall

 #get the second number from the user and place it in $t1
li $v0, 5 #load syscall read_int into v0
syscall #call the system
move $t1, $v0 # move the content of v0, which is the second number to t1 

la $a0,string_4
li $v0,4
syscall

 #get the second number from the user and place it in $t1
li $v0, 5 #load syscall read_int into v0
syscall #call the system
move $t2, $v0 # move the content of v0, which is the second number to t1

 move $a0,$t0
 move $a1,$t1
 move $a2,$t2
 jal eqzero # call to the eqzero procedure
 jal avrge # call to the avrge procedure

move $v1,$s1
 la $a0,string_5 
 li $v0,4
 syscall
 move $a0,$v1
 li $v0,1
 syscall
 jal exist

# here we will see if all numbers =0 exist ... if not ... go to the average procedure
eqzero: 

beq $a0 , $a1 , label_1
jr $ra
label1:
beq $a0 , $a2,label_2
jr $ra
label_2:
beq $a0 , $0,label_3
jr $ra

label_3:
 la $a0,string_6 
 li $v0,4
 syscall
 jal exist


avrge:

add $s0,$a0,$a1
add $s0, $s0,$a2

div $s1,$s0,3


jr $ra


exist:
li $v0,10
syscall

تم تعديل هذه المشاركة بواسطة Xacker في 27 مايو 2010 في 19:35

#2

ما هي رسائل الخطأ التي تظهر ؟

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#3

من قراءة الكود هذا الجزء يحوي مشكلة

 move $a0,$t0
 move $a1,$t1
 move $a2,$t2
 jal eqzero # call to the eqzero procedure
 jal avrge # call to the avrge procedure

تحاولين التحقق فيما إذا كانت الأرقام الثلاثة تساوي الصفر.

من أجل هذا اتبعي الطريقة التالية

طبقي عملية OR بين المسجل $0 والقيمة الأولى $t0 واحفظي الناتج في مسجل جديد

طبقي عملية OR بين المسجل الجديد والقيمة الثانية واحفظي الناتج في ذات المسجل إن أمكن

طبقي عملية OR أخيرة بين المسجل الجديد والقيمة الثالثة واحفظي الناتج في ذات المسجل

تطبيق عملية OR بين الأرقام الثلاثة لن يدع مجالاً للشك في حال كونهم مساويين للصفر لأن التغيير في واحد منهم سينعكس في الناتج حتماً باستخدام OR (وجود بت يساوي 1 في أي خانة)

يمكنك حينها فحص قيمة السجل إن كانت مساوية لـ $0 (أي أنها صفر)

beq $0,r,label

حيث r هو المسجل الذي يحوي نتيجة عملية OR النهائية.

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#4

لا تظهر رسالة خطأ .. يشتغل تمااام ...

بس التشغيل يوقف عند نقطة معينة ومايكمل ... أضن الخطأ يمكن في طريقة إستدعاء function

والنقطة الي يوقف عندها اهنا >>>

beq $a0 , $a1 , label_1

178769596.png

#5

مشكووووووووووووور أخوي على التوضيح والمسااااعدة ... :)

بس ما أدري يعني طريقتي خطأ :unsure: ؟؟؟

أنا عشان أتأكد في البداية خليت المين ميثود تستدعي eqzero عشان تتأكد إذا كانو يساون 0 أو لا وهذا نحن متفقين عليه ..

بعدين انقارن ما إذا a0 وهو المدخل الأول = a1 إذا كان الشرط صحيح

go to label_1

label_1 يحتوي على مقارنة ثانية بين a1 مع a2 وإذا تحقق الشرط يروح لlabel_2

label_2 يحتوي على مقارنة ما إذا كان a2 = 0 إذا اتحقق الشرط يطلع من البرنامج

وإذا لا يرجع للمين ميثود ويحسب معدل الأرقام

أحس الفكرة طويلة شوي .. بس هذي محاااولتي الأولى أسوي فيها هالبرنامج يعني ممكن اتكون أفكاري فيها أخطاء :excl: ...

ومشكوووووووور ويزااااك الله ألف خيرأخوووي مرة ثااانية على مسااااعدتك,,,, :)

#6

كتبتها بهذا الشكل

.data
string_1:.asciiz"calculate the average of three numbers:\n"
string_2:.asciiz"Enter the first number:\n"
string_3:.asciiz"Enter the second number:\n"
string_4:.asciiz"Enter the third number:\n"
string_5:.asciiz"the average number is:\n"
string_6:.asciiz"please change your input!\n\n"
string_7:.asciiz"\nand the remainder is:\n"

.text
main:

la 	$a0,string_1
li 	$v0,4
syscall

la 	$a0,string_2
li 	$v0,4
syscall

#get the first number from the user and place it in $t0
li	$v0, 5 		#load syscall read_int into v0
syscall 		#call the system
move 	$t0, $v0 	# move the content of v0, which is the first number to t0

la 	$a0,string_3 
li 	$v0,4
syscall

#get the second number from the user and place it in $t1
li 	$v0, 5 		#load syscall read_int into v0
syscall 		#call the system
move 	$t1, $v0 	# move the content of v0, which is the second number to t1 


la 	$a0,string_4
li 	$v0,4
syscall

#get the second number from the user and place it in $t1
li 	$v0, 5 		#load syscall read_int into v0
syscall 		#call the system
move 	$t2, $v0 	# move the content of v0, which is the second number to t1

move	$a0,$t0
or	$a0,$a0,$t1
or	$a0,$a0,$t2
bne	$a0,$0,not_zero

la 	$a0,string_6 
li 	$v0,4
syscall
j	main

not_zero:
#calculate average, no need for a procedure
add	$s0,$s0,$t0
add	$s0,$s0,$t1
add	$s0,$s0,$t2
div	$s1,$s0,3

mfhi	$s2

la	$a0,string_5 
li 	$v0,4
syscall

move	$v1,$s1
move 	$a0,$v1
li 	$v0,1
syscall

la	$a0,string_7
li	$v0,4
syscall


move	$v1,$s2
move 	$a0,$v1		#$HI = remainder, check: http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html
li 	$v0,1
syscall

li $v0,10
syscall

آخذاً بعين الاعتبار احتمال وجود باق remainder

للعلم فإن المسجل $HI يحتفظ بباقي القسمة فأقوم بتنفيذ mfhi لأنقل القيمة إلى أحد المسجلات وأظهرها لاحقاً.

لم أستخدم procedures فلا داع لاستخدام jal إلا لو كان المطلوب كتابة عملية average في proc كشرط.

البرنامج لا يحوي أخطاء فقد قمت بتجربته.

post-7008-127499211065_thumb.png

تم تعديل هذه المشاركة بواسطة Xacker في 27 مايو 2010 في 23:28

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#7

:lol:

شكرا أخي الكريم .. ويزاااك الله كل الخير ... ^^ :D

اشتغل عندي الكود ... ولكن عندي أسئلة ... :rolleyes:

في أشيااء أول مرة أتعامل معاها .. ولا مرة استخدمناها فإذا ممكن تفهمني.. وإذا ممكن نستخدم طريقة ثانية بدالها ... وإلي هم ...

or $a0,$a0,$t1

or $a0,$a0,$t2

mfhi $s2>>>> هل ممكن أستبدلها بشي آخر ... لأن ولا مرة اتكلم عنها الإستاااذ :sad:

والمطلوب منا في هذا الكود شي إجباري أنا نستخدم إستدعاء للفنكشن إلي تحسب معدل الأرقااام (jal avrge ) :sleep:

#8

هذا هو شكل الكود المطلوب .....

وشكرا أخي الكريم ... على المساااعدة ...

لغيت الرمايندر لأني ما فهمت الطريقة ... !! :wacko: بس تعلمت شي يديد :happy:

.data
string_1:.asciiz"calculate the average of three numbers:\n"
string_2:.asciiz"Enter the first number:\n"
string_3:.asciiz"Enter the second number:\n"
string_4:.asciiz"Enter the third number:\n"
string_5:.asciiz"the average number is:\n"
string_6:.asciiz"please change your input!\n\n"
string_7:.asciiz"\nand the remainder is:\n"

.text
main:
# first load the string1 + string2 ..

la   $a0,string_1
li    $v0,4
syscall

la   $a0,string_2
li    $v0,4
syscall


#get the first number from the user and place it in $t0
li         $v0, 5              #load syscall read_int into v0
syscall                        #call the system
move  $t0, $v0          # move the content of v0, which is the first number to t0

la      $a0,string_3 
li      $v0,4
syscall

#get the second number from the user and place it in $t1
li      $v0, 5                #load syscall read_int into v0
syscall                        #call the system
move    $t1, $v0        # move the content of v0, which is the second number to t1 


la      $a0,string_4
li      $v0,4
syscall

#get the  third number from the user and place it in $t2
li      $v0, 5          #load syscall read_int into v0
syscall                 #call the system
move    $t2, $v0        # move the content of v0, which is the second number to t2

#........................................................................................................................
# put the parameter to pass to a procedure,
move    $a0,$t0
move    $a1,$t1
move    $a2,$t2

# Here we are check if the input number=0 or not 
or      $a0,$a0,$a1
or      $a0,$a0,$a2
bne     $a0,$0,not_zero

# if numbers are =0  prompt the user and exit 
la      $a0,string_6 
li      $v0,4
syscall
j       main       # go back to the main ..

# if numbers are not = 0 go to the avrage procedure

not_zero: 
jal avrage # call avrage procedure



#.....................................................................................................................
# in this procedure calculate average number and print it .. 
avrage:
#calculate average,
add     $s0,$s0,$a0
add     $s0,$s0,$a1
add     $s0,$s0,$a2
div     $s1,$s0,3

#..........................................................................................................................
# print the result on the screen  .......
la      $a0,string_5 
li      $v0,4
syscall

move    $v1,$s1
move    $a0,$v1
li      $v0,1
syscall


li $v0,10
 syscall

:excl: سؤال يديد .... <<<

إذا كنت أريد أن طبااعة معدل أرقام في المين وليس في avrage procedure ... يعني

avrage procedure :

do caculation and go back to the main

jr $ra

main :

print the result

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

أنا جربتها ... بس ما تضبط يوقف التشغيل :ohmy: ...

>>>

تم تعديل هذه المشاركة بواسطة Xacker في 28 مايو 2010 في 21:16

#9
A33 كتب:

or      $a0,$a0,$t1

or      $a0,$a0,$t2

OR عملية منطقية تنفذ على مستوى البت.

لنفرض أني أريد التحقق من رقمين، إن كانا صفرين أم أحدهما أو كلاهما رقم آخر لا يساوي الصفر.

نعتبر الرقم A=5 والرقم B=8

يتم تمثيل A بشكل ثنائي (أي binary) بالقيمة 0101

يتم تمثيل B بشكل ثنائي بالقيمة 1000

يمكن مراجعة كيف تعمل OR على هذا الرابط: http://en.wikipedia.org/wiki/Bitwise_operation

لو طبقت OR بين A و B سيكون الناتج: 1101 يساوي العدد العشري 13

بالتالي يمكنني استخدام تعليمة bne أو beq وأفحص تساوي القيمة مع $0 التي تمثل الصفر في MIPS.

مثال ثاني، A=1, B=0

تنفيذ عملية OR بالطبع سيعطي النتيجة 1

لذلك ترين أنه مهما كانت الأرقام المدخلة فإن تنفيذ OR بينهما سيعطي رقم جديد لا يساوي الصفر في حال كان أحد أو كل الأرقام لا تساوي الصفر وهذا أفضل بكثير من فحص كل قيمة على حدة. أنصحك باستخدام هذه الطريقة فأنت تدرسين علوم حاسب أو ما شابه لا يجب أن تلزمني نفسك فقط بما يلقنوك إياه في المنهاج وبكل الأحوال الطريقة ليست اختراع ذرة حتى يحاسبوا على استخدامها فهي الأصل!

اقتباس

mfhi    $s2>>>> هل ممكن أستبدلها بشي آخر ... لأن ولا مرة اتكلم عنها الإستاااذ   :sad:

في جميع عمليات القسمة هناك عدد صحيح هو ناتج القسمة وهناك باقي remainder

مثلاً 5/2 يساوي 2 والباقي 1 (أو هو 2.5 لكننا هنا لا نتعامل مع أرقام فاصلة عشرية floating point numbers)

لحساب معدل 3 أرقام سنحتاج إلى جمع الأرقام وتقسيمها على 3، ماذا لو كان المجموع لا يقبل القسمة على 3 بدون باقي ؟ هل نهمل الباقي ؟ طبعاً لا لذلك قمت بإدراج فكرته في الإجابة.

تعليمة mfhi تعني move from $HI register حيث يتم وضع باقي القسمة في المسجل $HI بعد تنفيذ عملية DIV (مرة أخرى راجعي استخدام DIV في مراجع تعليمات MIPS)

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

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#10


not_zero:
jal avrage # call avrage procedure



#.....................................................................................................................
# in this procedure calculate average number and print it ..
avrage:
#calculate average,
add     $s0,$s0,$a0
add     $s0,$s0,$a1
add     $s0,$s0,$a2
div     $s1,$s0,3

#..........................................................................................................................
# print the result on the screen  .......
la      $a0,string_5
li      $v0,4
syscall

move    $v1,$s1
move    $a0,$v1
li      $v0,1
syscall


li $v0,10
syscall


لا أجد الكتابة صحيحة

استخدام subroutine/function يتطلب الدخول إلى هذا الـ subroutine، تنفيذه ومن ثم الخروج منه والعودة إلى داخل main.. هذا يتم من خلال استخدام jal مع jr وقد أهملتي استخدام jr في الكود الأخير.

مثال عن الاستخدام:

post-7008-12750714820276_thumb.png 

عدّلي البرنامج الذي أرفقتيه.

 

A33 كتب:

:excl:  سؤال يديد .... <<<

إذا كنت أريد أن طبااعة معدل أرقام في المين وليس في avrage procedure  ... يعني

avrage procedure  :

do caculation and go back to the main

jr $ra

main :

print the result

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

أنا جربتها ... بس ما تضبط  يوقف التشغيل  :ohmy:  ...  

>>>

حاولي حفظ القيمة في متغير ضمن البرنامج، لم أجرّب من قبل.

أو استخدمي الـ stack في حفظ القيمة واستعادتها في main ;)

اقرأي هذا الملف بتمعن:

http://user.it.uu.se/~justin/Teaching/NewDarkSlides/lecture5.pdf

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#11

شكـــــــــــــرا أخي الكريم بصراااحة فهمت الحمد الله :cool:

وعلى حسب ما فهمت من شرح (OR) .... يعني ممكن نستخدم أيضا (add) .. بحيث أن نجمع بمحتوى المدخل الأول والمدخل الثاني ونخزنهم في مسجل جديد

والمسجل الجديد نجمعة بلمدخل الثالث بعد ذلك نضع (beq) أو (bnq) ..لصفر ... يعني تقريبا مثل ما فهمت نفس (or) ...

وهذا آخر تعديل للكود أتمنى يكون صح :unsure:

.data
string_1:.asciiz"calculate the average of three numbers :\n"
string_2:.asciiz"Enter the first number:\n"
string_3:.asciiz"Enter the second number:\n"
string_4:.asciiz"Enter the THIRD number :\n"
string_5:.asciiz"the average number is :\n"
string_6:.asciiz"please change your input  :\n"

.text


main:

la $a0,string_1
li $v0,4
syscall



la $a0,string_2
li $v0,4
syscall

#get the first number from the user and place it in $t0
li $v0, 5  #load syscall read_int into v0
syscall     #call the system
move $t0, $v0  # move the content of v0, which is the first number to t0

    la $a0,string_3 
    li $v0,4
    syscall

 #get the second number from the user and place it in $t1
li $v0, 5 #load syscall read_int into v0
syscall   #call the system
move $t1, $v0  # move the content of v0, which is the second number to t1 

la $a0,string_4
li $v0,4
syscall

 #get the third number from the user and place it in $t2
li $v0, 5 #load syscall read_int into v0
syscall   #call the system
move $t2, $v0  # move the content of v0, which is the second number to t2

    move $a0,$t0
    move $a1,$t1
    move $a2,$t2
# Here we are check if the input number=0 or not 
or      $a0,$a0,$a1
or      $a0,$a0,$a2
bne     $a0,$0,not_zero

# if numbers are =0  prompt the user and exit 
la      $a0,string_6 
li      $v0,4
syscall

li $v0,10
syscall


# if numbers are not = 0 go to the avrage procedure

not_zero: 
jal avrge # call avrage procedure



    la $a0,string_5    
    li $v0,4
    syscall
    move $a0,$v1
    li $v0,1
    syscall

li $v0,10
syscall


avrge:

add $s0,$a0,$a1
add $s0, $s0,$a2

div $s1,$s0,3

move $v1,$s1

jr $ra

وشكــــــــــــــــــــــــــــــــــــــــــــــــــــــــــ :) ــــــــــــــرا جزيـــــــــلاااااا

تم تعديل هذه المشاركة بواسطة A33 في 29 مايو 2010 في 23:31

#12

صحيح إن شاء الله، جربيه بكل الأجوال فليس لدي PCSpim الآن قد قمت بإزالته بعد المرة الأولى.

بدلاً من تكرار

li $v0,10
syscall

يمكنك وضع لافتة والقفز إليها لو كانت الأرقام جميعها مساوية الصفر

# if numbers are =0  prompt the user and exit 
la      $a0,string_6 
li      $v0,4
syscall

j  fin


# if numbers are not = 0 go to the avrage procedure

not_zero: 
jal avrge # call avrage procedure



    la $a0,string_5    
    li $v0,4
    syscall
    move $a0,$v1
    li $v0,1
    syscall


fin:
li $v0,10
syscall

بالنسبة لكلامك حول تشابه OR و ADD... ممم لا يمكنك المقارنة بين الاثنين فلكل استخدامه ولا تنسي أن ADD تتضمن الجمع مع الحمل carry فمثلاًَ 1+1 = 1 و يوجد حمل 1 يضاف إلى الـ bits التالية.

بينما OR لا يوجد فيها حمل، 1 or 1 = 1 وفقط.

حاولي القراءة عن bitwise operators فهي مهمة جداً لدارسي علوم الحاسب ومن الغريب أنكم لستم على احتكاك جيد (أضعف الإيمان) بها.

استخدامي لـ OR الغرض منه فقط كشف في حال وجود بت واحد على الأقل يساوي الـ 1 في التمثيل الثنائي للأعداد بالتالي أن العدد ليس بصفر.

بالتوفيق راجياً من الله أن أكون قدمت ما فيه الفائدة.

تذكرة:

لا أدري لماذا شعرت أنك تساوين بين استخدام beq و bne

طبعاً التعليمتين مختلفتين للتذكرة والتنبيه.

bne = branch if not equal

beq = branch if equal 

Do as I say, not as I do

We are Anonymous. We are Legion. We don't forgive. We don't forget

#13
اقتباس

بالنسبة لكلامك حول تشابه OR و ADD... ممم لا يمكنك المقارنة بين الاثنين فلكل استخدامه ولا تنسي أن ADD تتضمن الجمع مع الحمل carry فمثلاًَ 1+1 = 1 و يوجد حمل 1 يضاف إلى الـ bits التالية.

بينما OR لا يوجد فيها حمل، 1 or 1 = 1 وفقط.

حاولي القراءة عن bitwise operators فهي مهمة جداً لدارسي علوم الحاسب ومن الغريب أنكم لستم على احتكاك جيد (أضعف الإيمان) بها.

استخدامي لـ OR الغرض منه فقط كشف في حال وجود بت واحد على الأقل يساوي الـ 1 في التمثيل الثنائي للأعداد بالتالي أن العدد ليس بصفر.

بالتوفيق راجياً من الله أن أكون قدمت ما فيه الفائدة.

:happy: ... جزااااااااااااك الله خير .... فهمت والحمد الله ...

اقتباس
تذكرة:

لا أدري لماذا شعرت أنك تساوين بين استخدام beq و bne

طبعاً التعليمتين مختلفتين للتذكرة والتنبيه.

bne = branch if not equal

beq = branch if equal

شكرا لك أخي الكريم .. أعرفها هذي المعلومة وأنا كنت أقصد أن ممكن نستخدم الثنتين باختلاف طبعا طريقتهم .. ^^ :)

جزااااااااااك الله كل الخير :)

مواضيع مشابهة