112 lines
		
	
	
		
			No EOL
		
	
	
		
			4.5 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			No EOL
		
	
	
		
			4.5 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
	AREA RESET, DATA, READONLY
 | 
						|
	EXPORT __Vectors
 | 
						|
__Vectors
 | 
						|
	DCD 0x10001000
 | 
						|
	DCD Reset_Handler
 | 
						|
	ALIGN
 | 
						|
 | 
						|
	AREA MYCODE, CODE, READONLY
 | 
						|
	ENTRY
 | 
						|
	EXPORT Reset_Handler
 | 
						|
 | 
						|
; ========================================================================================
 | 
						|
; Reset_Handler - Main program execution
 | 
						|
; ========================================================================================
 | 
						|
; Algorithm Overview:
 | 
						|
; 1. Load the hexadecimal value from memory
 | 
						|
; 2. Initialize BCD result accumulator (R4) to 0
 | 
						|
; 3. Initialize digit position multiplier (R11) to 1 (units place)
 | 
						|
; 4. Set loop counter for number of BCD digits to process
 | 
						|
; 5. In each iteration:
 | 
						|
;    a. Perform manual division by 10 using repeated subtraction
 | 
						|
;    b. The remainder (R2) is the current BCD digit (0-9)
 | 
						|
;    c. The quotient (R3) becomes the input for the next iteration
 | 
						|
;    d. Multiply digit by position value and add to BCD result
 | 
						|
;    e. Shift position multiplier left by 4 bits for next digit
 | 
						|
; 6. This version uses software division instead of hardware UDIV instruction
 | 
						|
 | 
						|
Reset_Handler
 | 
						|
	; Step 1: Initialize source pointer and load hexadecimal value
 | 
						|
	; R0 points to the hexadecimal value in memory
 | 
						|
	LDR	 R0, =SRR                      ; R0 = address of hexadecimal value
 | 
						|
 | 
						|
	; Load the hexadecimal value into R1
 | 
						|
	LDR	 R1, [R0]                      ; R1 = hexadecimal value (e.g., 0x45 = 69 decimal)
 | 
						|
 | 
						|
	; Step 2: Initialize BCD conversion variables
 | 
						|
	; R4 will accumulate the final BCD result
 | 
						|
	MOV	 R4, #0                        ; R4 = 0 (BCD result accumulator)
 | 
						|
 | 
						|
	; R11 holds the position multiplier for each BCD digit
 | 
						|
	; Starts at 1 for units place, shifts left by 4 bits each iteration
 | 
						|
	MOV	 R11, #1                       ; R11 = 1 (position multiplier)
 | 
						|
 | 
						|
	; Set loop counter for 3 BCD digits (maximum for byte values 0-255)
 | 
						|
	MOV	 R10, #3                       ; R10 = 3 (number of BCD digits to process)
 | 
						|
 | 
						|
	; Step 3: Main BCD conversion loop
 | 
						|
LOOP
 | 
						|
	; Prepare current value for division (copy R1 to R2)
 | 
						|
	MOV	 R2, R1                       ; R2 = R1 (dividend for this iteration)
 | 
						|
 | 
						|
	; Initialize quotient accumulator to 0
 | 
						|
	MOV	 R3, #0                        ; R3 = 0 (quotient accumulator)
 | 
						|
 | 
						|
	; Step 4: Manual division by repeated subtraction
 | 
						|
DIV_LOOP
 | 
						|
	; Compare dividend with divisor (10)
 | 
						|
	CMP	 R2, #10                       ; Compare R2 with 10
 | 
						|
 | 
						|
	; If dividend < 10, division is complete
 | 
						|
	BLT	 DIV_DONE                      ; Branch if R2 < 10
 | 
						|
 | 
						|
	; Subtract 10 from dividend (equivalent to R2 = R2 - 10)
 | 
						|
	SUB	 R2, R2, #10                   ; R2 = R2 - 10
 | 
						|
 | 
						|
	; Increment quotient (equivalent to quotient = quotient + 1)
 | 
						|
	ADD	 R3, R3, #1                    ; R3 = R3 + 1
 | 
						|
 | 
						|
	; Continue division loop
 | 
						|
	B	 DIV_LOOP                      ; Branch back to DIV_LOOP
 | 
						|
 | 
						|
	; Step 5: Division complete - R2 = remainder (0-9), R3 = quotient
 | 
						|
DIV_DONE
 | 
						|
	; Multiply the BCD digit (remainder) by its position value
 | 
						|
	; R8 = R2 * R11 = digit * position_multiplier
 | 
						|
	MUL	 R8, R2, R11                   ; R8 = digit * position_value
 | 
						|
 | 
						|
	; Add the weighted digit to the BCD result accumulator
 | 
						|
	ADD	 R4, R4, R8                    ; R4 = R4 + R8 (accumulate BCD digit)
 | 
						|
 | 
						|
	; Shift position multiplier left by 4 bits for next digit position
 | 
						|
	; Units (2^0) -> Tens (2^4) -> Hundreds (2^8) -> Thousands (2^12)
 | 
						|
	LSL	 R11, R11, #4                  ; R11 = R11 << 4 (next position)
 | 
						|
 | 
						|
	; Prepare quotient as input for next iteration
 | 
						|
	; The quotient becomes the new dividend for the next digit
 | 
						|
	MOV	 R1, R3                        ; R1 = R3 (use quotient for next iteration)
 | 
						|
 | 
						|
	; Decrement loop counter and set condition flags
 | 
						|
	SUBS R10, R10, #1                  ; R10 = R10 - 1, set flags for branch condition
 | 
						|
 | 
						|
	; Branch back to LOOP if counter is not zero
 | 
						|
	BNE	 LOOP                          ; If R10 != 0, continue loop
 | 
						|
 | 
						|
	; Step 6: Program termination
 | 
						|
	; The BCD result is stored in R4 but never saved to memory
 | 
						|
STOP
 | 
						|
	B STOP                             ; Branch to STOP label (infinite loop)
 | 
						|
 | 
						|
; ========================================================================================
 | 
						|
; Data Section - Hexadecimal Source Value
 | 
						|
; ========================================================================================
 | 
						|
; SRR contains the hexadecimal value: 0x45 (69 in decimal)
 | 
						|
; This will be converted to BCD format using manual division by repeated subtraction.
 | 
						|
; For value 69:
 | 
						|
; First iteration: 69 / 10 = 6 (quotient) with remainder 9
 | 
						|
; Second iteration: 6 / 10 = 0 (quotient) with remainder 6
 | 
						|
; Result: BCD = 0x69 (6 in tens place, 9 in units place)
 | 
						|
; In BCD: 0110 1001 = 0x69
 | 
						|
SRR DCD 0x45                          ; Hexadecimal value to be converted to BCD
 | 
						|
 | 
						|
	END                                ; End of the assembly program |