Skip to content

Instantly share code, notes, and snippets.

@Joursoir
Last active January 15, 2021 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Joursoir/9a926c7459c9ffabeb16a81cf6db1b4a to your computer and use it in GitHub Desktop.
Save Joursoir/9a926c7459c9ffabeb16a81cf6db1b4a to your computer and use it in GitHub Desktop.
.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