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

برنامج معرفة إذا كان العدد أولي أم لا

مغلق
بدأه Ahmadte1 في 24 أكتوبر 2006 · 11 رد · 1,964 مشاهدة · في لغة Assembly لأنظمة 16, 32, 64 بت
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

هذا الكود كتبته لمعرفت غذا كان العدد أولي أم لا و لكنه لا يظهر أي نتيجة

.model  tiny
.code
org 100h
start:
jmp primarystart
str1 db "Enter Number $"
str2 db "Is primary $"
str3 db "Not primary $"
number db ?
primarystart:
	mov ah,09h
	mov dx,offset str1
	int 21h

	mov ah,3fh
	mov dx,offset number
	int 21h
mov al,number
mov ah,0
push ax
call isprimary
pop ax
cmp ax,0
jz no
	mov ah,09h
	mov dx,offset str2
	int 21h
no:
	mov ah,09h
	mov dx,offset str3
	int 21h
jmp end

isprimary:
	pop dx
	mov cx,dx
	sub cx,2
	mov bl,2
	bb:
	mov ax,dx
	div bl
	cmp ah,0
	jz nono
		inc bl
		loop bb	
		jmp endloop
	nono:
		push 0
		retn
	endloop:
		push 1
retn

end:
	mov ah,4ch
	int 21h
end start

أرجو المساعدة :s

شكوت لوكيع سوءحفظـي ____ فأرشدني إلى ترك المعاصي

وقال لــــي إن العــلم نـــور ____ونـور الله لا يؤتــى لعــــاصي

#2

السلام عليكم

البرنامج يحوي نوعين من الأخطاء...

اخطاء عادية واخطاء جوهرية

اما الاخطاء الجوهرية فهي :

1- انت تستخدم

.model tiny ؟؟؟؟؟؟؟

هل تظن نفسك تعمل على asm32 !!! هذه asm16 !!!

يجب استخدام الـ segments ...هكذا :

mystack	segment stack
	db 512 dup (?)
mystack	ends

mydata   segment

...

mydata   ends

mycode   segment
	assume cs:mycode , ds:mydata
main	 proc
start:
	org 100h
	mov ax,offset mydata
	mov ds,ax

...

main endp
mycode   ends
end start

2- يجب عليك التمييز بين الـ strings والـ values

فعندما تستخدم احدى المقاطعات لاستقبال النص من المستخدم فهذا النص يكون عبارة عن string

لكن هذه الـ string ينقصها علامة الـ $ في نهايتها لذلك يجب عليك ان تضيفها بنفسك

وبالتالي عند كتابتك لاوامر مثل

mov ax,dx

div bl

فانت هنا تريد قسمة الرقم الذي ادخله المستخدم...لكن هذا الرقم ينقصه عمليتين قبل استخدامه في القسمة :

* اولا يجب ان تضيف اليه علامة $ في النهاية

ولهذا فعند تعريفك للـ buffer الذي سيستقبل النص من اليوزر ، عليك تعريفه هذا :

	number db  512,?  512  dup (?)

اول عنصر في المصفوفة (في المتغير) هو 512 وهو يشير الى حجم المتغير والعنصر الثاني ؟ هو number of bytes actually read

(لا اعرف السبب في استخدامه لكن هكذا قرات في احد الكتب ، وعندما حاولت الاستغناء عنه اظهر لي خطا ، عموما دعك منه الان)

المثال التالي (ليس مني) يشير الى كيفية استقبال نص من اليوزر ثم اضافة $ اليه يدويا ثم طباعته

										 org 100h
										 mov dx, offset buffer
										 mov ah, 0ah
										 int 21h
										 jmp print
										 buffer db 10,?, 10 dup(' ')
										 print:
										 xor bx, bx
										 mov bl, buffer[1]
										 mov buffer[bx+2], '$'
										 mov dx, offset buffer + 2
										 mov ah, 9
										 int 21h

* ثانيا يجب ان تحوله من ASCII الى numeric value وذلك بطرح 30 منه...لماذا 30 ؟ عد الى جدول ASCII

وسترى ان الاعداد تبدا من 30 الى 39 ، اي ان الرقم 5 قيمته 35 ، لذلك للتحويل من ASCII الى قيمة رقمية نطرح 30

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

اما الاخطاء العادية فهي :

1- الكلمات المحجوزة للغة الاسمبلي لا يمكن استخدامها كــ label ...كلمة end

عليك تغييرها...اجعلها end1 مثلا...

2- المعامل (operand) لاوامر الـ push و pop لا يمكن ان يكون قيمة فورية (immediate value)

ارى انك كتبت push 0 وهذا خطأ

والصوابب

mov bx,0

push bx

3- لماذا تستخدم الخدمة رقم int 21h/03Fh في استقبال النص من اليوزر ؟؟؟ هذه لا علاقة لها بالامر

والمفروض استخدام الخدمة رقمint 21h/0ah

ملاحظة 1:

من المفيد استخدام الـ parameter التالي : /z عند استخدام masm

فمثلا

masm program

تصبح

masm program/z

هكذا سيعرض لك السطر الذي ظهر به الخطا ، واسفل منه نوع الخطا...مما يسهل عملية استكشاف الاخطاء وتصحيحها

ملاحظة 2:

الفكرة التي عرضتها (والتي لم اعرف كيفية تنفيذها ) قد لا تكون الابسط...فكر في استخدام تعليمة مثل AAA او شيء من هذا القبيل كما قال لي xacker .

تحياتي

allko/ATRE

تم تعديل هذه المشاركة بواسطة allko في 25 أكتوبر 2006 في 03:00

#3

تعديل :

بخصوص ما قلت انه خطأ جوهري ، اي انك لم تستخدم الـ segments

لم اكن على صواب...فبامكانك الستخدام اي من الطريقتين في العنونة...اما الطريقة التي ذكرتها

.model small/tiny

او طريقة العنونة التي وضعت لك مخططها العام...كل الطريقتين تؤديان الى نفس النتيجة

اما خصوص اضافة علامة $ فهذا في حالة ان الرقم الذي ادخله المستخدم يتكون من اكثر من خانة

اما اذا كان مكونا من خانة واحدة فلا حاجة لذلك.

(وسنفترض انك تتعامل مع ارقام من خانة واحدة ، لانه في حال كانا لرقم مكوننا من خانتين فستحتاج الى الكثير من التعديلات وليس فقط اضافة $ في النهاية...)

تم تعديل هذه المشاركة بواسطة allko في 25 أكتوبر 2006 في 05:04

#4

السلام عليكم أخي allko

اقتباس
هل تظن نفسك تعمل على asm32 !!! هذه asm16 !!!

أنا بالفعل أريد عمل البرنامج على asm16

اقتباس
.model tiny ؟؟؟؟؟؟؟

أنا أسف نسيت أن أذكر أنني أستعمل TASM وأنني أكتب برنامج لا حقته .com :unsure:

اقتباس
...لماذا 30

وكأني قرأتها أن الرقم 1 يبدأ من 49

اقتباس
والمفروض استخدام الخدمة رقمint 21h/0ah

جربتها ولم تعمل شيئ (ربما لم أعرف كيف أستخدمها)

اقتباس
الفكرة التي عرضتها (والتي لم اعرف كيفية تنفيذها ) قد لا تكون الابسط

هذا بالظبط ما أيقنته عند البدأ بعملها :lol:

و لن كان هدفي أن أكتب بعض البرامج الت فيها بعض التعقيد على asm16

اقتباس
هذا القبيل كما قال لي xacker .

ونحن بانتظار قدومه

جزاك الله خيرا عدلت الكود ليصبح هكذا

ولكنه لم يعمل

هو لا يظهر إلا رسالة Enter number

ثم يستقبل الرقم ويذهب(ينتهي)دون إظهار النتيجة

.model  tiny
.code
org 100h
start:
jmp primarystart
str1 db "Enter Number $"
str2 db "Is primary $"
str3 db "Not primary $"
number db ?
primarystart:
	mov ah,09h
	mov dx,offset str1
	int 21h

	mov ah,01h
	mov dx,offset number
	int 21h
sub number,48
mov al,number
mov ah,0
push ax
call isprimary
pop ax
cmp ax,0
jz no
	mov ah,09h
	mov dx,offset str2
	int 21h
no:
	mov ah,09h
	mov dx,offset str3
	int 21h
jmp end1

isprimary:
	pop dx
	mov cx,dx
	sub cx,2
	mov bl,2
	bb:
	mov ax,dx
	div bl
	cmp ah,0
	jz nono
		inc bl
		loop bb	
		jmp endloop
	nono:
		mov ax,0
		push ax
		retn
	endloop:
		mov ax,1
		push ax
retn

end1:
	mov ah,4ch
	int 21h
end start

شكوت لوكيع سوءحفظـي ____ فأرشدني إلى ترك المعاصي

وقال لــــي إن العــلم نـــور ____ونـور الله لا يؤتــى لعــــاصي

#5

حلت المشكلة ;)

الكود

.model  tiny
.code
org 100h
start:
jmp primarystart
str1 db "Enter Number $"
str2 db "Is primary $"
str3 db "Not primary $"
primarystart:
	mov ah,09h
	mov dx,offset str1
	int 21h

	mov ah,01h
	int 21h
sub al,48
mov ah,0
call isprimary
cmp ax,0
jz no
	mov ah,09h
	mov dx,offset str2
	int 21h
	jmp end1
no:
	mov ah,09h
	mov dx,offset str3
	int 21h
jmp end1

isprimary proc near
	push ax
	pop dx
	cmp dx,2
	jnz next
		mov ax,1
		retn
	next:
	mov cx,dx
	sub cx,2
	mov bl,2
	bb:
	mov ax,dx
	div bl
	cmp ah,0
	jz nono
		inc bl
		loop bb	
		jmp endloop
	nono:
		mov ax,0
		retn
	endloop:
		mov ax,1
retn
endp

end1:
	mov ah,4ch
	int 21h
end start

ولكن كيف سيعالج البرنامج الأرقام الكبيرة أكثر من خانة

شكوت لوكيع سوءحفظـي ____ فأرشدني إلى ترك المعاصي

وقال لــــي إن العــلم نـــور ____ونـور الله لا يؤتــى لعــــاصي

#6

ساعطيك الفكرة وقم بتنفيذها

الرقم المدخل عبارة عن تنسيق ASCII لذلك لن تستطيع التعامل معه كرقم, عليك اولا ان تقوم بتحويله الى شكله العشري decimal بطريقة ما

لنفرض ان الرقم هم 234, هذا الرقم سيخزن في الذاكرة بالقيمة 34 33 32

لذلك سنقوم بتخزين الرقم ضمن buffer بطول ما نحدده بالبداية

طالما مراتب الرقم مخزنة في بايتات مستقلة الامر سهل, نقوم بتشكيل حلقة ندور بها على هذه المراتب ونطرح 30h لنحصل على القيمة 04 03 02

الان نحن بحاجة للشكل العشري من هذا الرقم, الموضوع ايضا بسيط, علينا في البداية حساب طول الرقم المدخل, هناك خدمة من خدمات المقاطعات مختصة بالادخال وتقوم باعادة طول القيمة المدخلة في احد المسجلات, للاسف لم اعد اذكر ما هي.. عليك بالبحث.

حتى لو لم تتوفر المقاطعة, تستطيع ان تقوم باجراء حلقة لتتحق من ان الرقم الموجود في المصفوفة buffer[reg] ليس 0h على ان يزيد reg بمقدار 1 اي هو قيمة مسجل يزيد بمقدار 1 وعندما تصل الى قيمة buffer[n]=0h يكون طول المدخل هو n-1

هذا الرقم سيكون عداد الحلقة التي سندخل بها والتي ستقوم بضرب المرتبة الكبرى (في هذا المثال هي مرتبة الألوف) بالعدد (10 power n) ثم ننتقل الى المرتبة الادنى لنضرب الرقم بـ 10^n ايضا وفي هذه الحالة ستكون n قد نقصت بمقدار 1 وهكذا.. لكن هنا تكمن مشكلة معينة, عليك الانتباه الى ان الحلقة يجب ان تكون من n-1 وليس n كي يكون العدد في النهاية 10^(n=0) كي يصبح 1 عند ضربه بمرتبه الآحاد.

الى هنا نكون قد قمنا بتشكيل رقم (ست-عشري) مجزء وبقي فقط ان نجمع هذه المراتب لنحصل على الرقم الست عشري المطلوب, الموضوع بسيط. لاحظ ان عملية الطرح والضرب ثم الجمع جعلت المعالج يقوم بتحويل هذه الارقام الى اجزاء ست عشرية وجمعها وبالتالي تخلصنا من مرحلة معقدة في تحويل الرقم الى ست عشري تحت DOS.

الان طالما ان الرقم اصبح بالحالة الست عشرية في احد المسجلات اصبحت مسالة التحقق من كونه prime سهلة كما فعلت في حال الرقم الواحد.

بالتوفيق

Do as I say, not as I do

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

#7

السلام عليكم

اقتباس
لنضرب الرقم بـ 10^n

لا تقل لي يدويا :blink:

شكوت لوكيع سوءحفظـي ____ فأرشدني إلى ترك المعاصي

وقال لــــي إن العــلم نـــور ____ونـور الله لا يؤتــى لعــــاصي

#8

هذا يوضح الفكرة

لكن به بعض الاخطاء البسيطة

.model small
.code
org 100h
start:
jmp begin
 buf   db  512,?,   512 dup (?)   
str1  db  "prime $"
str2  db  "not prime $"

begin:
;recieving the number
	mov ah,0ah
	mov dx,offset buf
	int 21h

;adding $
	xor bx, bx
	mov bl, buf[1]
	mov buf[bx+2], '$'

;converting into numeric value
xor dx,dx
conv:
	cmp buf[dx+2],500h		  ; assuming $=500h
	inc dx							  ; dx= # of digits
	jne conv
	push dx

	sub  offset buf[dx],30		 ;first digit (at the most right)
	sub  offset buf[dx-1],30	 ; second digit
	mov ah,10
	mov bl, offset buf[dx-1]
	mul bl					 ; multiplying second digit by 10
	mov offset buf[dx-1],bl
power:
	mov ah,10
	mul ah						  ;   ax=10 * 10	 
	sub offset buf[dx-3],30		  ; this subs 30 from 'cx' digit...
	mov bx,ax					 ; maybe there is no need for this line...wait...
	mov bl,offset buf[dx-3]					
	mul bl						 ;... and multiplies it by ...
	mov  offset buf[dx-3] , bl
	dec dl 
	cmp dl,0
	jne power
	pop dx

;  time to add something
xor ax,ax
addition:
   add ax,offset buf[dx]
   dec dx
   cmp dx,0
   jne addition

  xor bx,bx
  mov bl,2
isprime?:
  mov ax,dx
  div bl
  cmp ah,0	; is there a reminder?
  inc bx
  jne isprime?
  cmp bx,dx
  je prime

	mov ah,09h				
	mov dx,offset str2			;not prime
	int 21h
	jmp end1

prime:
	mov ah,09h
	mov dx,offset str1
	int 21h
end1:
	mov ah,4ch
	int 21h

end start

انا افترض ان العدد المدخل مكون من3 خانات على الاقل

لاحظ انني ضربت اول وثاني خانتين خارج اللوب وليس داخلها...

تم تعديل هذه المشاركة بواسطة allko في 25 أكتوبر 2006 في 23:47

#9

شكرا أخي allko

ما قصده ب

اقتباس
لا تقل لي يدويا

التالي

كنا في باقي لغات البرمج نكتب

مثلا c++

pow(10,n)

الفيجول

10^n

ألا يوجد مثل هذا في ال asm

(إرتباط بمكتبة كما في c++ )

(math.h)

شكوت لوكيع سوءحفظـي ____ فأرشدني إلى ترك المعاصي

وقال لــــي إن العــلم نـــور ____ونـور الله لا يؤتــى لعــــاصي

#10

لا ، لا يمكن

#11
اقتباس
لا ، لا يمكن
:huh: :blink:

شكوت لوكيع سوءحفظـي ____ فأرشدني إلى ترك المعاصي

وقال لــــي إن العــلم نـــور ____ونـور الله لا يؤتــى لعــــاصي

#12

هل نسيت ان هذا 16بت ولا يوجد له مكتبات ربط *-)

Do as I say, not as I do

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

هذا الموضوع مغلق.

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

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…