| .ORG 0x1000
DivisionDemo:
ADIW R26, 0 ; If no parameter was passed in a command
BREQ AEarly_Ret ; line tail, just exit immediately
MOVW R24, R26 ; Point to the buffer and parse any value
CALL AParseValue ; string which it
SBRS R21, BIT_PV_VALID ; Exit if no value could be parsed
Early_Ret:
RET
ADIW R26, 0 ; If the first ParseValue() function returned
BREQ AEarly_Ret ; no pointer, there's no point in going on
CALL APushAll ; Since quite a few will be needed
MOVW R2, R22 ; LSWord of the dividend
MOVW R4, R24 ; MSWord of the dividend
MOV R6, R21 ; BIT_PV_... FLAGs returned by ParseValue()
MOVW R24, R26 ; Point to the remaining command line tail
CALL AParseValue
SBRS R21, BIT_PV_VALID ; If a second value (the divisor) was able
RJMP APopAll_Ret ; to be parsed, it is in R25:R24:R23:R22
MOVW R10, R22 ; LSWord of the divisor
MOVW R12, R24 ; MSWord of the divisor
MOV R14, R21 ; BIT_PV_... FLAGs 2nd ParseValue() returned
MOVW R22, R2 ; Move the first value parsed (the dividend)
MOVW R24, R4 ; into R25:R24:R23:R22
MOV R19, R6 ; In order to use the BIT_PV_NEGATIVE FLAG
LDI R27, ACSZ_Divided >> 8 ; Point to the string to print afterward
LDI R26, ACSZ_Divided & 0xFF
RCALL ADisplayValueAndString ; The local subroutine, below
MOVW R22, R10 ; Move the divisor (2nd value) parsed into
MOVW R24, R12 ; R25:R24:R23:R22
MOV R19, R14 ; The FLAGs the second ParseValue() returned
LDI R27, 0x3AD2 >> 8 ; Pointer to the " = ", which already exists
LDI R26, 0x3AD2 & 0xFF ; in FLASH memory
RCALL ADisplayValueAndString
MOVW R22, R2 ; Now setup for the actual division:
MOVW R24, R4 ; load the numerator in R25:R24:R23:R22
MOVW R18, R10 ; load the denominator in R21:R20:R19:R18
MOVW R20, R12
OR R6, R14 ; Combine to get a single sign bit
SBRS R6, BIT_PV_NEGATIVE ; If neither were specified as negative
CALL ADivide2ULONGs ; values, perform an unsigned division
SBRC R6, DBIT_PV_NEGATIVE
CALL ADivide2LONGs ; Otherwise, call the signed division logic
CALL ADumpRegisters
MOVW R10, R18 ; Save the remainder, which was returned in
MOVW R12, R20 ; R21:R20:R19:R18
MOV R19, R25 ; Quotient is already in R25:R24:R23:R22
LDI R27, ACSZ_Remain >> 8
LDI R26, ACSZ_Remain & 0xFF
RCALL ADisplayValueAndString
MOVW R22, R10 ; Move the remainder to R25:R24:R23:R22
MOVW R24, R12 ; to setup to display it
MOV R19, R25
LDI R27, 0x3AE0 >> 8 ; 0x3AE0 is the string 0x0D, 0x0A, NULL
LDI R26, 0x3AE0 & 0xFF ; (Carriage Return, Line Feed, NULL)
RCALL ADisplayValueAndString
PopAll_Ret:
JMP APopAll ; Must use a JUMP for every PopAll
DisplayValueAndString:
LDI R21, 0 ; Set copy desination = NULL pointer
LDI R20, 0
LDI R18, 1 << BIT_FMT_PRINT | 1 << BIT_FMT_COMMAS
SBRC R19, BIT_PV_NEGATIVE ; Select based on the sign BIT passed
ORI R18, 1 << BIT_FMT_SIGNED
CALL AFormatULONG
MOVW R24, R26 ; Transfer the string point to R25:R24
JMP APrintFLASHASCIIz
CSZ_Divided: .STRING " divided by "
CSZ_Remain: .STRING " remainder " |
| Test it: |
m>@ 4096 1000 99
1,000 divided by 99 = 10 remainder 10
m>@ 4096 0xC00000 0x765
12,582,912 divided by 1,893 = 6,647 remainder 141
m>@ 4096 -1000 10
-1,000 divided by 10 = -100 remainder 0
m>@ 4096 -1000 -98
-1,000 divided by -98 = 10 remainder 20
m>@ 4096 0x8000001 4
134,217,729 divided by 4 = 33,554,432 remainder 1
m> ; There are so many possibilities; just try some
m>
|