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 |