Last active
January 15, 2021 14:13
-
-
Save Joursoir/9a926c7459c9ffabeb16a81cf6db1b4a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.include "m16def.inc" | |
.def shift = r19 ; start defines | |
.def temp = r20 | |
.cseg ; start segment of code | |
.org 0 | |
argv: .db 62, 3, 251, 50; arguments: A B C D | |
ldi ZH, high(argv) ; pointer to arguments | |
ldi ZL, low(argv) | |
ldi r16, high(RAMEND) ; start init stack | |
out sph, r16 | |
ldi r16, low(RAMEND) | |
out spl, r16 ; end init stack | |
ldi r16, 0xFF | |
out DDRD, r16 ; setting port D to exit | |
start: | |
/* | |
Reverse Polish notation: | |
R = A, B, 4, C, +, 2, /, +, 3, /, +, D, 3, *, + | |
*/ | |
lpm r16, Z+ ; argument A to r16 | |
push r16 | |
lpm r16, Z+ ; argument B to r16 | |
push r16 | |
ldi r16, 4 | |
lpm r17, Z+ ; argument C to r17 | |
add r16, r17 ; = 4 + C | |
brcs end ; check overflow | |
; (4 + C) / 2 = R18 | |
lsr r16 ; shift to right for divide by 2 | |
pop r17 ; read argument B from stack | |
add r16, r17 ; = (B + (4 + C) / 2) | |
brcs end ; check overflow | |
ldi r17, 3 | |
rcall uns_shift_div ; (B + (4 + C) / 2) / 3 = R18 | |
pop r16 ; read argument A from stack | |
add r18, r16 ; = A + (B + (4 + C) / 2) / 3 | |
brcs end ; check overflow | |
push r18 ; push result above to stack | |
lpm r16, Z ; argument D to r16 | |
cpi r16, 86 ; check overflow | |
brcc end | |
ldi r17, 3 | |
rcall uns_shift_multip ; D * 3 = R18 | |
pop r16 ; read (A + (B + (4 + C) / 2) / 3) from stack | |
add r18, r16 ; = A + (B + (4 + C) / 2) / 3 + D * 3 | |
brcs end ; check overflow | |
out PortD, r18 ; return answer to Port D | |
end: ; endless loop | |
rjmp end | |
; ======= Some realization of divide ======= | |
; | |
; R16 - dividend | |
; R17 - divisor | |
; R18 - quotient (answer) | |
; | |
uns_sub_div: | |
clr r18 ; clear answer register | |
sl_sub_div: | |
sub r16, r17 ; = dividend - divisor | |
brlo end_sub_div ; end loop if r16 < r17 | |
inc r18 ; increase answer | |
rjmp sl_sub_div ; repeat loop | |
end_sub_div: | |
ret ; return from func | |
uns_shift_div: | |
clr temp ; clear temporary register | |
clr r18 ; clear answer (also used to count to 8 | |
; count to 8 division steps, | |
inc r18 ; 1 at start) | |
sl_shift_div: ; Here the division loop starts | |
clc ; clear carry-bit | |
rol r16 ; rotate the next bit of the number | |
; to the temporary register | |
rol temp | |
brcs roll_shift_div ; a one has rolled left, so subtract | |
cp temp, r17 ; Division result 1 or 0? | |
brcs clc_shift_div ; jump over subtraction, if temp < r17 | |
roll_shift_div: | |
sub temp, r17 ; number - divisor | |
sec ; set carry-bit is 1 | |
rjmp l_shift_div ; jump over clear carry-bit | |
clc_shift_div: | |
clc ; clear carry-bit | |
l_shift_div: | |
rol r18 ; rotate carry-bit into answer register | |
brcc sl_shift_div ; while zero rotate to carry-bit: | |
; repeat division loop | |
ret ; return from func | |
; ======= Some realization of multiplier ======= | |
; | |
; R16 - multiplicand | |
; R17 - multiplier | |
; R18 - product (answer) | |
; | |
uns_add_multip: | |
clr r18 ; clear answer register | |
; r16 - number of loop | |
; r17 - sum each loop | |
sl_add_multip: | |
cpi r16, 0 ; r16 == 0? | |
breq el_add_multip ; end loop if yes (see above) | |
add r18, r17 ; add multiplier to answer | |
dec r16 ; decrease number of loop | |
rjmp sl_add_multip ; repeat loop | |
el_add_multip: | |
ret ; return from func | |
uns_shift_multip: | |
clr r18 ; clear answer register | |
ldi shift, 8 ; set shift register to high bit | |
; (number of loop) | |
sl_shift_multip: | |
sbrs r16, 0 ; if first bit of multiplicand == 1 then | |
rjmp il_shift_mutip ; SKIP THIS command | |
ldi temp, 0b11111111 | |
and temp, r17 ; "logical multiplier" | |
add r18, temp ; add result to answer | |
il_shift_mutip: | |
lsr r16 ; shift multiplicand to right | |
lsl r17 ; shift multiplier to left | |
dec shift ; decrease shift register (number of loop) | |
brne sl_shift_multip ; IF shift != 0 THEN repeat loop | |
ret ; return from func |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment