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

مشكلة في التحويل من النظام الثنائي

بدأه alsu_wh في 7 مايو 2013 · 3 رد · 1,322 مشاهدة · في لغة Assembly لأنظمة 16, 32, 64 بت
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

اخواني الكرام:

احاول عمل برنامج للتحويلبين انظمة الاعداد حيث يقوم المستخدم باختيار النظام ومن ثم يدخل رقم ويقوم البرنامج بعرض القيمة بالنظام العشري، الست عشري. مثلا يتم ادخال الرقم الثنائي 110 ويتم عرض القيمة 6 بالعشري والقيمة 6 ست عشري. البرنامج مشاي تمام مع جميع الصيغ ماعدا الثنائي. المشكلة هي كيف اقرأ الرقم بالثنائي ومن ثم تحويله الى عشري وست عشري. البرنامج بالكود المرفق علما بأني استخدم 32-bit. 

وشكرا لمروركم

 

مشكلتي تحديدا في هذه الدالة

 

;-----------------------------------------------
ReadBin PROC
;
;  THE PROBLEM IS IN THIS PROCEDURE
;-----------------------------------------------
 
push ecx
push eax
push esi
push edx
mov edx,OFFSET binVal ;point to the beginning of the binary string
mov ecx,SIZEOF binVal
mov esi,0
call ReadString ;input a string from the keyboard
mov binCounter,eax ;number of characters
mov ecx,binCounter
;MOV CX,16 ; number of digits
XOR BX,BX
 
MOV AH,1
L1:
mov al,binVal[esi]
CMP AL,0DH
JE END_INPUTB
 
AND AL,0FH ; convert to digit
SHL BX,1
OR BL,AL ; insert in BL
 
LOOP L1
 
END_INPUTB:
 
MOV AX,BX
 
POP DX
POP CX
POP BX
 
 
RET
ReadBin ENDP
 
وهذا البرنامج كامل للتوضيح
 
INCLUDE irvine32.inc

.data
num DWORD 5
binCounter DWORD ?
binVal BYTE 17 DUP(0)
prompt BYTE "Welcome to the Binary/Decimal/Hex Converter", 0
invalid BYTE "Invalid value, please try again", 0
hexPrompt BYTE "Enter the hexadecial number and press enter key: ",0
DecPrompt BYTE "Enter the decimal number and press enter key: ",0
binPrompt BYTE "Enter the binary number and press enter key: ",0
numInHex BYTE "The number in hexadecimal format: ",0
numInDec BYTE "The number in decimal format: ",0
numInBin BYTE "The number in binary format: ",0
menu BYTE "Press number corresponding to the ation you would like to take.",0DH,0AH
	BYTE "1. If you would like to convert a decimal to binary and hexadecimal.",0DH,0AH
	BYTE "2. If you would like to convert a binary nuber to decimal and hexadecimal.",0DH,0AH
	BYTE "3. If you would like to convert a hexadecimal number to decimal and binary.",0DH,0AH
	BYTE "4. If you would like to quit the application.",0DH,0AH

.code
main PROC

	mov edx, OFFSET prompt
	call WriteString
another:
	call Crlf
	mov edx,OFFSET menu
	call WriteString
	call ReadDec
	cmp eax,4
	je stop
	cmp eax,3
	je fromHex
	cmp eax,2
	je fromBin
	cmp eax,1
	je fromDec
	mov edx,OFFSET invalid
	call WriteString
	;call Crlf
	jmp another

fromHex:
	mov edx,OFFSET hexPrompt
	call WriteString
	call ReadHex
	call print_dec
	call print_bin
	jmp another

fromDec:
	mov edx,OFFSET decPrompt
	call WriteString
	call ReadDec
	call print_hex
	call print_bin
	jmp another

fromBin:
	mov edx,OFFSET binPrompt
	call WriteString
	call ReadBin
	call print_dec
	call print_hex
	jmp another

stop:
	call Crlf
	exit
 main ENDP


;-----------------------------------------------
ReadBin PROC
;
;  THE PROBLEM IS IN THIS PROCEDURE
;-----------------------------------------------
		
		push ecx
		push eax
		push esi
		push edx
		mov edx,OFFSET binVal	;point to the beginning of the binary string
		mov	ecx,SIZEOF binVal
		mov	esi,0
		call ReadString		;input a string from the keyboard
		mov binCounter,eax		;number of characters
		mov ecx,binCounter
		;MOV CX,16		; number of digits
		XOR BX,BX
		
		MOV AH,1
L1:		
		mov al,binVal[esi]
		CMP AL,0DH
		JE	END_INPUTB
		
		AND AL,0FH		; convert to digit
		SHL	BX,1
		OR BL,AL		; insert in BL
		
		LOOP L1
		
	END_INPUTB:
	
		MOV	AX,BX
		
		POP DX
		POP CX
		POP BX
		
		
		RET
	ReadBin ENDP	

 ;-----------------------------------------------
print_hex PROC
;
;-----------------------------------------------
	 mov	  edx,OFFSET numInHex
	 call  WriteString
	 call WriteHex
 	 call Crlf
	
	 ret
print_hex ENDP


;-----------------------------------------------
print_dec PROC
;
;-----------------------------------------------
	 mov	  edx,OFFSET numInDec
	 call  WriteString
	 call WriteDec
	 call Crlf 
	 ret
print_dec ENDP

;-----------------------------------------------
print_bin PROC
;
;-----------------------------------------------
	 mov	  edx,OFFSET numInBin
	 call  WriteString
	 call WriteBin
	 call Crlf
	 
	 ret
print_bin ENDP
 
END main
#2

1- المتغير binVal مساحته 17 بايت و المفترض ان يكون 32 حيث كل حرف مدخل - صفر أو واحد - سيتم تخزينة فى 1 بايت.

2- انت افترضت ان القيمة المدخله ستكون صفر او واحد و لم تتحقق من وجود قيمة أخرى.

3- لم تتحقق من أن مساحة النص المدخل أقل من او تساوى مساحة binVal.

 

الكود التالي يقوم بتحويل النص الذى يحتوى على "010111010" إلى قيمة رقمية تحفظ داخل eax، أيضا يقوم بالتحقق من محتويات النص المدخل قبل التحويل. توجد بعض الملاحظات:

1- الكود التالي يفترض ان مساحة binVal هي 32.

2- النص المعاد من ReadString يحفظ داخل binVal و مساحة النص المدخل من المستخدم يتم العوده بها داخل eax.

3- فى النهاية القيمة المقابلة للنص الموجود داخل binVal يتم العودة حفظها داخل eax.

4- لابد ان تقوم بتعريف النصين msg_TooManyInputs و msg_InvalidInputs حيث الأول يشير إلى أن عدد حروف النص المدخل أكبر من 32 و الثاني يشير إلى ان النص المدخل يحتوى على حروف غير 0 و 1.

 

الكود قد يحتوى على اخطاء حيث انى لم اقم بتجربته:

	push eax
	push ebx
	push ecx
	push edx

	; get input string
	mov edx, offset binVal
	mov ecx, sizeof binVal

	call ReadString
	cmp eax, 0 ; check zero input
	jz  ZeroInput
	cmp eax, 32 ; at max 32 input characters. 32 characters for 32 bits
	jg  TooManyInputs


	; validate input string
	mov ebx, eax ; save input string length
	xor ecx, ecx ; set counter to zero
Validate:
	mov eax, binVal[ecx] ; move character at ecx to eax
	sub eax, 30h ; subtract character '0' from input to get digit value
	cmp eax, 0 ; compare value with zero
	jl  InvalidInputs ; if less than zero signal error
	cmp eax, 1 ; compare value with one
	jg  InvalidInputs ; if greater than one signal error
	inc ecx ; increment ecx by 1
	cmp ebx, ecx ; compare length
	jg  Validate

; input string is valid, convert value
	mov dl, BYTE PTR ebx ; save string size in cl
	dec dl
	xor cl, cl
	; cl have index of character inside binVal
	; dl have index of bit inside eax

Convert:
	mov ebx, binVal[cl] ; move character at cl to ebx
	sub ebx, 30h ; subtract character '0' from input to get digit value
	shl ebx, dl  ; shift 0 or 1 by dl bits
	or  eax, ebx ; or ebx with eax
	dec dl ; get location of next bit
	inc cl ; get location of next character
	cmp dl, 0
	jnz Convert

	; last character
	mov ebx, binVal[cl] ; move character at index 0 to ebx
	sub ebx, 30h ; subtract character '0' from input to get digit value
	or  eax, ebx
	jmp ProcEnd

ZeroInput:
	xor eax, eax
	jmp ProcEnd

TooManyInputs:
	mov edx,OFFSET msg_TooManyInputs
	call WriteString
	xor eax, eax
	jmp ProcEnd

InvalidInputs:
	mov edx,OFFSET msg_InvalidInputs
	call WriteString
	xor eax, eax

ProcEnd:
	pop edx
	pop ecx
	pop ebx
	pop eax
	ret

 

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

تم تعديل هذه المشاركة بواسطة C++er في 7 مايو 2013 في 23:32

مدونتي: C++ Tips and Tricks

#3

smile.png بارك الله فيك اخي محمد وجزاك الله الف خير. افتخر باني عضو في هذا المنتدى الرائد منذ عام ٢٠٠١، ومع مرور الايام تزداد ثقتي بكم. 

في الحقيقة ابهرتني بردك السريع، راح اجرب الكود واعمل التعديلات اللي بالملاحظات و اوافيك بالنتيجة.

يعجز لساني عن شكرك اخي الكريم.

#4

أخي محمد، لم استطع تصحيح الاخطاء

الكود لوغارثميا صحيح و معظم الاخطاء ناتجة عن اختلاف المساحة في الرجيسترات اثناء النقل.

عموما الكود التالي يشمل بعض التعديلات و ارجو تجرب الكود حتى نظهر الاخطاء بشكل أوضح لديك:

 

INCLUDE irvine32.inc

.data
num DWORD 5
binCounter DWORD ?
binVal BYTE 32 DUP(0)
temp BYTE 0
prompt BYTE "Welcome to the Binary/Decimal/Hex Converter", 0
invalid BYTE "Invalid value, please try again", 0
hexPrompt BYTE "Enter the hexadecial number and press enter key: ",0
DecPrompt BYTE "Enter the decimal number and press enter key: ",0
binPrompt BYTE "Enter the binary number and press enter key: ",0
numInHex BYTE "The number in hexadecimal format: ",0
numInDec BYTE "The number in decimal format: ",0
numInBin BYTE "The number in binary format: ",0
msg_InvalidInputs BYTE "Invalid binary value! Number in binary formate include only 0,1",0
msg_TooManyInputs BYTE "ERROR! The entered binary is more than 32 digit"
menu BYTE "Press number corresponding to the ation you would like to take.",0DH,0AH
	BYTE "1. If you would like to convert a decimal to binary and hexadecimal.",0DH,0AH
	BYTE "2. If you would like to convert a binary nuber to decimal and hexadecimal.",0DH,0AH
	BYTE "3msg_InvalidInputs If you would like to convert a hexadecimal number to decimal and binary.",0DH,0AH
	BYTE "4. If you would like to quit the application.",0DH,0AH

.code
main PROC

	mov edx, OFFSET prompt
	call WriteString
another:
	call Crlf
	mov edx,OFFSET menu
	call WriteString
	call ReadDec
	cmp eax,4
	je stop
	cmp eax,3
	je fromHex
	cmp eax,2
	je fromBin
	cmp eax,1
	je fromDec
	mov edx,OFFSET invalid
	call WriteString
	;call Crlf
	jmp another

fromHex:
	mov edx,OFFSET hexPrompt
	call WriteString
	call ReadHex
	call print_dec
	call print_bin
	jmp another

fromDec:
	mov edx,OFFSET decPrompt
	call WriteString
	call ReadDec
	call print_hex
	call print_bin
	jmp another

fromBin:
	mov edx,OFFSET binPrompt
	call WriteString
	call ReadBin
	call print_dec
	call print_hex
	jmp another

stop:
	call Crlf
	exit
 main ENDP


;-----------------------------------------------
ReadBin PROC
;
;  THE PROBLEM IS IN THIS PROCEDURE
;-----------------------------------------------
		
		push eax
	push ebx
	push ecx
	push edx

	; get input string
	mov edx, offset binVal
	mov ecx, sizeof binVal

	call ReadString
	cmp eax, 0 ; check zero input
	jz  ZeroInput
	cmp eax, 32 ; at max 32 input characters. 32 characters for 32 bits
	jg  TooManyInputs


	; validate input string
	mov ebx, eax ; save input string length
	xor ecx, ecx ; set counter to zero
Validate:
	mov al, binVal[ecx] ; move character at ecx to eax
	sub eax, 30h ; subtract character '0' from input to get digit value
	cmp eax, 0 ; compare value with zero
	jl  InvalidInputs ; if less than zero signal error
	cmp eax, 1 ; compare value with one
	jg  InvalidInputs ; if greater than one signal error
	inc ecx ; increment ecx by 1
	cmp ebx, ecx ; compare length
	jg  Validate

; input string is valid, convert value
	mov dl,32;BYTE PTR ebx ; save string size in cl
	dec dl
	xor cl, cl
	; cl have index of character inside binVal
	; dl have index of bit inside eax

Convert:
	mov ebx, binVal[cl] ; move character at cl to ebx
	sub ebx, 30h ; subtract character '0' from input to get digit value
	shl ebx, cl  ; shift 0 or 1 by dl bits
	or  eax, ebx ; or ebx with eax
	dec dl ; get location of next bit
	inc cl ; get location of next character
	cmp dl, 0
	jnz Convert

	; last character
	mov ebx, binVal[cl] ; move character at index 0 to ebx
	sub ebx, 30h ; subtract character '0' from input to get digit value
	or  eax, ebx
	jmp ProcEnd

ZeroInput:
	xor eax, eax
	jmp ProcEnd

TooManyInputs:
	mov edx,OFFSET msg_TooManyInputs
	call WriteString
	xor eax, eax
	jmp ProcEnd

InvalidInputs:
	mov edx,OFFSET msg_InvalidInputs
	call WriteString
	xor eax, eax

ProcEnd:
	pop edx
	pop ecx
	pop ebx
	pop eax
	ret
	ReadBin ENDP	

 ;-----------------------------------------------
print_hex PROC
;
;-----------------------------------------------
	 mov	  edx,OFFSET numInHex
	 call  WriteString
	 call WriteHex
 	 call Crlf
	
	 ret
print_hex ENDP


;-----------------------------------------------
print_dec PROC
;
;-----------------------------------------------
	 mov	  edx,OFFSET numInDec
	 call  WriteString
	 call WriteDec
	 call Crlf 
	 ret
print_dec ENDP

;-----------------------------------------------
print_bin PROC
;
;-----------------------------------------------
	 mov	  edx,OFFSET numInBin
	 call  WriteString
	 call WriteBin
	 call Crlf
	 
	 ret
print_bin ENDP

END main

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