prjbrook

forth85_09. Numberh OK

Jul 16th, 2014
239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.57 KB | None | 0 0
  1. ;this is forth85_09.
  2. ; task today is to get numberh working (all numbers of the form HHHH
  3. ; that are in the interpret line of words in buf 1 end up as binary on stack)
  4. ; plus all the pointers are right for the next word.
  5. ;numh seems to work OK. It stacks HHHHH ie hex vals with 4+ chars. The first 4 anyway.
  6. ; but still gives a STOP signal which will clear the tack anyway, later.
  7. ;next: save this then do 16 bit + and minus then play with stack nums.
  8. .NOLIST
  9. .include "tn85def.inc"
  10. .LIST
  11. .LISTMAC ;sometimes macro code gets in way of clarity in listing
  12. .MACRO header
  13. .db high(@0), low(@0), @1, @2
  14. .ENDMACRO
  15. .MACRO mypop
  16. ld @0,-y
  17. .ENDMACRO
  18. .MACRO mypush
  19. st y+, @0
  20. .ENDMACRO
  21. .MACRO mypop2
  22. mypop @0
  23. mypop @1
  24. .ENDMACRO
  25. .MACRO mypush2
  26. mypush @0
  27. mypush @1
  28. .ENDMACRO
  29. .MACRO pushx
  30. push xl
  31. push xh
  32. .ENDMACRO
  33. .MACRO popx
  34. pop xh
  35. pop xl
  36. .ENDMACRO
  37. .MACRO pushz
  38. push zl
  39. push zh
  40. .ENDMACRO
  41. .MACRO popz
  42. pop zh
  43. pop zl
  44. .ENDMACRO
  45.  
  46.  
  47. .def FOUND = r15 ;if found=1 we have a match of Ram word on dictionary
  48. .def BOTTOM = r14 ;have hit the bottom of the dict and not found a match
  49. .def STOP = r13 ;stop interpreting line of words
  50. .def STATE = r12
  51. .def FOUNDCOUNTER = r11 ;dealWithWord clicks this if found =1. Counts successful finds in dictionary.
  52. .def SECONDLETTER =r10 ;helpful for debugging
  53. .def vl = r22
  54. .def vh = r23 ; u,v,w,x,y,z are all pointers
  55. .DSEG
  56. .ORG 0x60
  57.  
  58. ;consts: .DB "jksdafhsdf",8, 255, 0b01010101, -128, 0xaa
  59. .equ BUF1LENGTH = 64
  60.  
  61. buf1: .byte BUF1LENGTH
  62. buf2: .byte 64 ;could have third buffer?
  63. varSpace: .byte 64 ;might need more than 32 variables
  64. ;.org 0x1E0
  65. myStackStart: .byte 64
  66.  
  67. .cseg
  68. .ORG 0x800 ;dictionary starts at 4K (2K words) mark
  69. ;----------------------------------------------------
  70. one_1:
  71. .db 0,0,3, "one" ;code for one
  72. one:
  73. ; rcall stackme
  74. rcall stackme_2
  75. .db 01, 00
  76. ret
  77. ;----------------------------------------------
  78. two_1:
  79. header one_1, 3, "two"
  80. two:
  81. rcall stackme_2
  82. .db 02,00
  83. ret
  84. ;------------------------------------------
  85. dup_1:
  86. header two_1,3,"dup"
  87. dup:
  88. mypop r17
  89. mypop r16
  90. mypush r16
  91. mypush r17
  92. mypush r16
  93. mypush r17
  94.  
  95. ret
  96. ;-------------------------------------------
  97. drop_1:
  98. header dup_1,4,"drop"
  99. drop:
  100. mypop r17
  101. mypop r16 ;TODO what if stack pointer goes thru floor?
  102. ret
  103. ;----------------------------------
  104. swapp_1: ;twp p's becasue assembler recognizes avr opcode swap
  105. header drop_1,5, "swapp"
  106. swapp:
  107. mypop2 r17,r16
  108. mypop2 r19,r18
  109. mypush2 r16,r17
  110. mypush2 r18,r19
  111. ret
  112.  
  113.  
  114. ;-------------------------------------------------
  115. ;shift this later
  116.  
  117. S_1:
  118. ;the EOL token that gets put into end of buf1 to stop parsing
  119. header swapp_1,1,"S"
  120. S:
  121. clr STOP
  122. inc STOP ;set time-to-quit flag
  123. ret
  124. ;------------------------------------------
  125.  
  126. fetch_1: ;doesn't like label = @-1
  127. ;classic fetch. (adr -- num). Only in RAM
  128. header S_1,1,"@"
  129. fetch:
  130. pushx ;going to use x to point so better save
  131. mypop xh
  132. mypop xl
  133. ld r16,x+
  134. ld r17,x
  135. mypush r16
  136. mypush r17 ; and put them on my stack
  137. popx ;return with x intact and RAM val on my stack
  138. ret
  139. ;dddddddddddddddddddddddddddddddddddddddddddddddd
  140.  
  141. cfetch_1: ;doesn't like label = c@-1
  142. ;classic fetch. (adr -- num). Only in RAM. Do I want y to advance just one byte on mystack
  143. header fetch_1,2,"c@"
  144. cfetch:
  145. pushx ;going to use x to point so better save
  146. mypop xh
  147. mypop xl
  148. ld r16,x+
  149. mypush r16
  150. popx ;return with x intact and RAM val on my stack
  151. ret
  152. ;dddddddddddddddddddddddddddddddddddddddddddddddd
  153.  
  154. store_1: ;classic != "store"(adr num --) . Num is now at cell adr.
  155. header cfetch_1,1,"!"
  156. store:
  157. mypop2 r17,r16 ;there goes the num
  158. pushx
  159. mypop2 xh,xl ;there goes the address
  160. st x+,r16
  161. st x,r17 ;num goes to cell with location=adr
  162. popx
  163. ret
  164. ;ddddddddddddddddddddddddddddddddddddddddddddddddddd
  165.  
  166. cstore_1: ;classic c!= "store"(adr 8-bitnum --) . 8 bit Num is now at cell adr.
  167. header store_1,2,"c!"
  168. cstore:
  169. mypop r16 ;there goes the num. Just 8 bits at this stage.
  170. pushx
  171. mypop2 xh,xl ;there goes the address
  172. st x+,r16
  173. ; st x,r17 ;num goes to cell with location=adr
  174. popx
  175. ret
  176. ;------------------------------------
  177.  
  178. star_1: ;classic 16*16 mulitply (n n -- n*n)
  179. header cstore_1,1,"*"
  180. star:
  181. mypop2 r17,r16
  182. mypop2 r19,r18 ;now have both numbers in r16..r19
  183. rcall mpy16s ; multiply them. Result in r18..r21. Overflow in r20,21
  184. mypush2 r18,r19
  185. ret
  186. ;-----------------------------------------
  187. LATEST:
  188. slashMod_1: ;classic /MOD (n m -- n/m rem)
  189. header star_1,4,"/mod"
  190. slashMod:
  191. mypop2 r19,r18 ; that's m
  192. mypop2 r17,r16 ;that's n
  193. rcall div16s ;the the 16 by 16 bit divsion
  194. mypush2 r16,r17 ;answer ie n/m
  195. mypush2 r14,r15 ;remainder
  196. ret
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203. ;-------------------------------------------------
  204. stackme_2: ;stacks on my stack next 16bit num. Address of 16bit number is on SP-stack
  205. ; Used like this stackme_2 0034. Puts 0034 on myStack and increments past number on return stack.
  206. pop r17
  207. pop r16 ; they now contain eg 0x0804 which contain the 16bit num
  208. movw zl,r16 ;z now points to cell that cobtains the number
  209. clc
  210. rol zl
  211. rol zh ;double word address for z. lpm coming up
  212.  
  213.  
  214.  
  215. lpm r16,z+
  216. lpm r17,z+ ;now have 16bit number in r16,17
  217.  
  218. st y+,r16
  219. st y+, r17 ;mystack now contains the number
  220.  
  221. clc
  222. ror zh
  223. ror zl ;halve the z pointer to step past the number to return at the right place
  224.  
  225. push zl
  226. push zh
  227.  
  228. ret
  229.  
  230.  
  231.  
  232. ;====================================================================================================
  233.  
  234. .ORG 0
  235. rjmp start
  236. typein: .db " one two 14568 1298", 0x0d
  237.  
  238. ;stackme dropx onex stackme swap drop",0x0d
  239. start:
  240. ldi r16, low(RAMEND)
  241. out SPL, r16
  242. ldi r16,high(RAMEND)
  243. out SPH, r16
  244.  
  245. ldi YL,low(myStackStart)
  246. ldi YH,high(myStackStart)
  247.  
  248. ;rjmp test_interpretLine
  249. ;rjmp test_cfetch
  250. ;rjmp test_store
  251. ;rjmp test_cstore
  252. ;rjmp test_mpy16s
  253. ;rjmp test_mpy16s0
  254. ;rjmp test_star
  255. ;rjmp test_div16s
  256. ;rjmp test_slashMod
  257. ;rjmp test_Hex4ToBin2
  258. rjmp test_interpretLine
  259.  
  260. rjmp start
  261.  
  262. getline0: ;force a line into buf1 via flash string. Simulates GETLINE
  263. ldi zl, low(typein<<1)
  264. ldi zh, high(typein<<1)
  265. ldi xl, low(buf1)
  266. ldi xh, high(buf1)
  267. type0:
  268. lpm r16,Z+
  269. st x+,r16
  270. cpi r16,0x0d ;have we got to the end of the line?
  271. brne type0
  272. ret
  273. ;--------------------------------------------
  274. ;WORD gets x to point to start of word (copy in w=r24,25) with the length in len = r20
  275. ;assume word points to somewhere in buf1. Should advance thru spaces=0x20 to first real char
  276. word: ;maybe give it a header later
  277. ld r16,x+ ;get char
  278. ld SECONDLETTER, x ;for debugging
  279.  
  280. cpi r16,0x20 ;is it a space?
  281. breq word ;if so get next char
  282. ;if here we're point to word start. so save this adr in w
  283. mov r24,xl
  284. mov r25,xh ;wordstart now saved in w
  285.  
  286.  
  287. clr r20 ;length initially 0
  288. nextchar:
  289. inc r20 ;r20 = word length
  290. ld r16,x+ ;get next char
  291. cpi r16,0x20
  292. brne nextchar
  293. dec r24 ;adjust start of word
  294. ;if here we've found a word.Starting at w length in r20.x points to space just past word
  295. ret
  296. ;----------------------------------------
  297.  
  298. compare: ;given a word in buf1 and a word in the dic are they the same? The word in the dic is pointed to by Z.
  299. ; and the word in buf1 is pointed to by w=r24,25. len = r20. Z on entry points to the link. Needs +2 to
  300. lpm r23,z+
  301. lpm r22,z+ ;store next link in v=r22,23. z now points to len byte
  302.  
  303. startc:
  304. push r20 ;save length
  305. lpm r16,Z+ ;length of dictionary word, first entry now in r16
  306. cp r16,r20 ;same lengths?
  307. brne outcom ;not = so bail out
  308. ;if here the words are the same length, what about the rest of the chars.First get x to point to word.
  309. mov xl,r24
  310. mov xh,r25 ;x now point to start of buf1 word
  311. upcom:
  312. lpm r16,z+
  313. ld r17,x+ ;get one corresponding char from each word
  314. cp r16,r17 ;same word?
  315. brne outcom ;bail out if chars are different
  316. dec r20 ;count chars
  317. brne upcom ;still matching and not finished so keep going
  318. ;if here r20 is 0 so match must have been perfect so FOUND = 1
  319. clr FOUND
  320. inc FOUND
  321. outcom:
  322. pop r20 ;get old lngth of buf1 word back
  323. ret
  324. ;-------------------------------------------
  325. jmpNextWord: ;go to next word in the dictionary. Assume v=r22,23 contains next link word(not byte)
  326. ; and w = r24,25 contains RAM word start with len in r20
  327. ;exit with z pointing to next word ready for next COMPARE.
  328. clc
  329. rol r22
  330. rol r23 ;above 3 instructions change word address into byte address by doubling
  331. movw r30,r22 ;z now points to next word
  332. ret
  333. ;-----------------------------------------
  334.  
  335. doLatest: ;set up so first jump in dictionary is to top=LATEST and other flags set up.
  336. ldi vl, low(LATEST)
  337. ldi vh, high(LATEST)
  338. clr FOUND
  339. clr BOTTOM ;not yet found the match, not yet at the bottom. Either will stop search.
  340. clr STOP ;keep parsing words til this goes to a 1
  341. ret
  342. ;---------------------------------------------
  343. interpretLine: ;given line of words in buf one, search for words one by one. Don't do code
  344. ; or compile at this stage, just find and report that and go into next one.
  345. rcall getline0 ;change later to real getline via terminal
  346. rcall pasteEOL
  347. ldi xl, low(buf1)
  348. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  349. clr FOUNDCOUNTER ;counts finds in line parsing.
  350.  
  351. nextWord:
  352. tst STOP
  353. brne stopLine
  354. rcall word
  355. rcall findWord ;not done yet
  356. rcall dealWithWord ;go and run code STATE=0, or compile (STATE =1).{ c0de, comp1le}
  357. rjmp nextWord
  358. stopLine:
  359. ret
  360. ;-----------------------------------------------------------------
  361. findWord:
  362. rcall doLatest
  363. upjmpf:
  364. rcall jmpNextWord
  365. rcall compare
  366. tst FOUND
  367. brne stopsearchf ;if last compare got a match (FOUND=1) then stop searching
  368. tst vl
  369. brne upjmpf ;if v=0000 then we've hit the bottom of the dictionary
  370. tst vh
  371. brne upjmpf ;not found and not at bottom so keep going
  372. ;if here FOUND =0, ie no match yet and we've hit the bottom of the dictionary
  373. clr BOTTOM
  374. inc BOTTOM ;exit with FOUND=0 and BOTTOM =1
  375. stopsearchf: nop
  376. ret
  377. ;----------------------------
  378. test_interpretLine:
  379. rcall interpretLine
  380. til: rjmp til ;** with r24 pointing to 'S' and FOUND = r15 =1
  381. ;------------------------------
  382. dealWithWord: ;come here when it's time to compile or run code
  383. ;Good debugging spot. Enter here with Z pointing to CFA of word found. Y points to myStack. X points to just
  384. ; past the word we are seeking (w-s). r10 is 2nd letter of w-s. w = start adr of w-s. v is a link
  385. ; to the next word in dic. Either just below the found word or 0000 if we get to the bottome with no match
  386. ;
  387. nop
  388. tst FOUND
  389. breq notfound
  390. inc FOUNDCOUNTER
  391.  
  392. ;want to hop over filler bytes,0's added to keep codes on even byte boundaries
  393. ; so if r30 is odd at this stage inc it. odd is lsbit = 1.
  394. sbrs r30,0 ;skip next instruction if final bit lsb = 1
  395. rjmp downdw
  396. ;if here lsb = 1 so we're on a padding byte and have to add 1 to get to a 2 byte boundary
  397. inc r30
  398. brcc downdw
  399. inc r31 ;add one to z before converting to bytes
  400.  
  401. downdw:
  402. clc
  403. ror zh
  404. ror zl ;put z back into word values
  405.  
  406.  
  407. rcall executeCode
  408.  
  409.  
  410.  
  411. .MESSAGE "Word found"
  412. rjmp outdww
  413. notfound:
  414. nop
  415. ; .MESSAGE "Word not found"
  416. ; clr STOP
  417. ; inc STOP ;stop parsing line
  418. rcall numberh ; word not in dict so must be a number? Form = HHHH
  419. ;now have to add 3 to x so it points past this word ready not next one
  420. clc
  421. inc r26
  422. inc r26
  423. inc r26
  424. brcc outdww
  425. inc r27 ;but only if overflow
  426. nop
  427. outdww:
  428. ret ;with STOP =1 in not a number
  429. ;------------------------------------------------------------------------
  430. pasteEOL: ;when a line of text is TYPEd into buf1 it should end with CR=$0d. This gets replaced with ]}, a
  431. ; special end of line word. When the word is invoked it casues a QUIT back to the waiting for input stage.
  432. ; Start at buf1 start and inspect each char for a $0D. When found replace with a "$20 S $20 "
  433. ldi xl, low(buf1)
  434. ldi xh, high(buf1) ;pnt to start of buffer
  435. clr r17
  436. nxtChar:
  437. inc r17 ;r17 is counter. Bail out when r17 > BUF1LENGTH
  438. cpi r17, BUF1LENGTH -4
  439. breq outProb
  440. ld r16, x+
  441. cpi r16, $0d
  442. brne nxtChar
  443. ;if here we've found a $0d in buf1 before the end, so replace with an EOL token. x points to just after it.
  444. ldi r16,$20
  445. st -x, r16 ;back up. Then go forward.
  446. ; ldi r16, ']'
  447. st x+, r16
  448. ldi r16,'S'
  449. st x+, r16
  450. ; ldi r16, '}'
  451. ; st x+, r16
  452. ldi r16, $20
  453. st x, r16
  454. rjmp outpel
  455.  
  456.  
  457. outProb:
  458. nop
  459. .MESSAGE "Couldn't find $0d"
  460. outpel:
  461. ret
  462.  
  463. ;-------------------------------------
  464. executeCode: ;with Z pointing to cfa. Not sure whether to jmp or call
  465.  
  466. ijmp
  467. ret
  468. ;---------------------------------------
  469. test_fetch: ;do run thru of @
  470. rcall getline0 ;change later to real getline via terminal
  471. rcall pasteEOL
  472. ldi xl, low(buf1)
  473. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  474.  
  475. ldi r16,$62
  476. mypush r16
  477. ldi r16,$0
  478. mypush r16 ;should now have adr $0062 on mystack
  479. rcall fetch
  480. tf1:
  481. rjmp tf1
  482. ;---------------------------------
  483. test_cfetch: ;do run thru of @
  484. rcall getline0 ;change later to real getline via terminal
  485. rcall pasteEOL
  486. ldi xl, low(buf1)
  487. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  488.  
  489. ldi r16,$62
  490. mypush r16
  491. ldi r16,$0
  492. mypush r16 ;should now have adr $62 on mystack
  493. rcall cfetch
  494. tcf1:
  495. rjmp tcf1
  496. ;----------------------------
  497. test_store:
  498. rcall getline0 ;change later to real getline via terminal
  499. rcall pasteEOL
  500. ldi xl, low(buf1)
  501. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  502. ldi r16,$62
  503. ldi r17,$0
  504. mypush2 r16,r17 ;should now have adr $62 on mystack
  505. ldi r16, $AB
  506. ldi r17, $CD
  507. mypush2 r16,r17 ;now have $ABCD on mystack
  508. rcall store
  509. ts1:
  510. rjmp ts1
  511. ;------------------------
  512. test_cstore:
  513. rcall getline0 ;change later to real getline via terminal
  514. rcall pasteEOL
  515. ldi xl, low(buf1)
  516. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  517. ldi r16,$62
  518. ldi r17,$0
  519. mypush2 r16,r17 ;should now have adr $62 on mystack
  520. ldi r16, $AB
  521. ; ldi r17, $CD
  522. mypush r16 ;now have $ABCD on mystack
  523. rcall cstore
  524.  
  525. ts11:
  526. rjmp ts11
  527. ;Now put arith routines here. Are from AVR200. Just using 16*16 for * but get 32bit result.
  528.  
  529.  
  530. ;***************************************************************************
  531. ;*
  532. ;* "mpy16s" - 16x16 Bit Signed Multiplication
  533. ;*
  534. ;* This subroutine multiplies signed the two 16-bit register variables
  535. ;* mp16sH:mp16sL and mc16sH:mc16sL.
  536. ;* The result is placed in m16s3:m16s2:m16s1:m16s0.
  537. ;* The routine is an implementation of Booth's algorithm. If all 32 bits
  538. ;* in the result are needed, avoid calling the routine with
  539. ;* -32768 ($8000) as multiplicand
  540. ;*
  541. ;* Number of words :16 + return
  542. ;* Number of cycles :210/226 (Min/Max) + return
  543. ;* Low registers used :None
  544. ;* High registers used :7 (mp16sL,mp16sH,mc16sL/m16s0,mc16sH/m16s1,
  545. ;* m16s2,m16s3,mcnt16s)
  546. ;*
  547. ;***************************************************************************
  548.  
  549. ;***** Subroutine Register Variables
  550.  
  551. .def mc16sL =r16 ;multiplicand low byte
  552. .def mc16sH =r17 ;multiplicand high byte
  553. .def mp16sL =r18 ;multiplier low byte
  554. .def mp16sH =r19 ;multiplier high byte
  555. .def m16s0 =r18 ;result byte 0 (LSB)
  556. .def m16s1 =r19 ;result byte 1
  557. .def m16s2 =r20 ;result byte 2
  558. .def m16s3 =r21 ;result byte 3 (MSB)
  559. .def mcnt16s =r22 ;loop counter
  560.  
  561. ;***** Code
  562. mpy16s: clr m16s3 ;clear result byte 3
  563. sub m16s2,m16s2 ;clear result byte 2 and carry
  564. ldi mcnt16s,16 ;init loop counter
  565. m16s_1: brcc m16s_2 ;if carry (previous bit) set
  566. add m16s2,mc16sL ; add multiplicand Low to result byte 2
  567. adc m16s3,mc16sH ; add multiplicand High to result byte 3
  568. m16s_2: sbrc mp16sL,0 ;if current bit set
  569. sub m16s2,mc16sL ; sub multiplicand Low from result byte 2
  570. sbrc mp16sL,0 ;if current bit set
  571. sbc m16s3,mc16sH ; sub multiplicand High from result byte 3
  572. asr m16s3 ;shift right result and multiplier
  573. ror m16s2
  574. ror m16s1
  575. ror m16s0
  576. dec mcnt16s ;decrement counter
  577. brne m16s_1 ;if not done, loop more
  578. ret
  579. ;----------------------------------------------------------
  580. ;***** Multiply Two Signed 16-Bit Numbers (-12345*(-4321))
  581. test_mpy16s:
  582. ldi mc16sL,low(-12345)
  583. ldi mc16sH,high(-12345)
  584. ldi mp16sL,low(-4321)
  585. ldi mp16sH,high(-4321)
  586. rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
  587. ;=$032df219 (53,342,745)
  588. tmpy: rjmp tmpy
  589.  
  590. test_mpy16s0:
  591. ldi mc16sL,low(123)
  592. ldi mc16sH,high(123)
  593. ldi mp16sL,low(147)
  594. ldi mp16sH,high(147)
  595. rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
  596. tmpy0: rjmp tmpy0
  597. ;-----------------------
  598. test_star:
  599. ldi r16,-$7b
  600. mypush r16
  601. ldi r16,$00
  602. mypush r16 ;that's decimal 123 on stack
  603. ldi r16,$93
  604. mypush r16
  605. ldi r16,$00
  606. mypush r16 ; and thats dec'147
  607. rcall star
  608. tsr: rjmp tsr
  609.  
  610. ;--------------------------
  611. ;***************************************************************************
  612. ;*
  613. ;* "div16s" - 16/16 Bit Signed Division
  614. ;*
  615. ;* This subroutine divides signed the two 16 bit numbers
  616. ;* "dd16sH:dd16sL" (dividend) and "dv16sH:dv16sL" (divisor).
  617. ;* The result is placed in "dres16sH:dres16sL" and the remainder in
  618. ;* "drem16sH:drem16sL".
  619. ;*
  620. ;* Number of words :39
  621. ;* Number of cycles :247/263 (Min/Max)
  622. ;* Low registers used :3 (d16s,drem16sL,drem16sH)
  623. ;* High registers used :7 (dres16sL/dd16sL,dres16sH/dd16sH,dv16sL,dv16sH,
  624. ;* dcnt16sH)
  625. ;*
  626. ;***************************************************************************
  627.  
  628. ;***** Subroutine Register Variables
  629.  
  630. .def d16s =r13 ;sign register
  631. .def drem16sL=r14 ;remainder low byte
  632. .def drem16sH=r15 ;remainder high byte
  633. .def dres16sL=r16 ;result low byte
  634. .def dres16sH=r17 ;result high byte
  635. .def dd16sL =r16 ;dividend low byte
  636. .def dd16sH =r17 ;dividend high byte
  637. .def dv16sL =r18 ;divisor low byte
  638. .def dv16sH =r19 ;divisor high byte
  639. .def dcnt16s =r20 ;loop counter
  640.  
  641. ;***** Code
  642.  
  643. div16s: mov d16s,dd16sH ;move dividend High to sign register
  644. eor d16s,dv16sH ;xor divisor High with sign register
  645. sbrs dd16sH,7 ;if MSB in dividend set
  646. rjmp d16s_1
  647. com dd16sH ; change sign of dividend
  648. com dd16sL
  649. subi dd16sL,low(-1)
  650. sbci dd16sL,high(-1)
  651. d16s_1: sbrs dv16sH,7 ;if MSB in divisor set
  652. rjmp d16s_2
  653. com dv16sH ; change sign of divisor
  654. com dv16sL
  655. subi dv16sL,low(-1)
  656. sbci dv16sL,high(-1)
  657. d16s_2: clr drem16sL ;clear remainder Low byte
  658. sub drem16sH,drem16sH;clear remainder High byte and carry
  659. ldi dcnt16s,17 ;init loop counter
  660.  
  661. d16s_3: rol dd16sL ;shift left dividend
  662. rol dd16sH
  663. dec dcnt16s ;decrement counter
  664. brne d16s_5 ;if done
  665. sbrs d16s,7 ; if MSB in sign register set
  666. rjmp d16s_4
  667. com dres16sH ; change sign of result
  668. com dres16sL
  669. subi dres16sL,low(-1)
  670. sbci dres16sH,high(-1)
  671. d16s_4: ret ; return
  672. d16s_5: rol drem16sL ;shift dividend into remainder
  673. rol drem16sH
  674. sub drem16sL,dv16sL ;remainder = remainder - divisor
  675. sbc drem16sH,dv16sH ;
  676. brcc d16s_6 ;if result negative
  677. add drem16sL,dv16sL ; restore remainder
  678. adc drem16sH,dv16sH
  679. clc ; clear carry to be shifted into result
  680. rjmp d16s_3 ;else
  681. d16s_6: sec ; set carry to be shifted into result
  682. rjmp d16s_3
  683.  
  684. ;-----------------------------------------------
  685.  
  686. test_div16s:
  687. ;***** Divide Two Signed 16-Bit Numbers (-22,222/10)
  688. ldi dd16sL,low(-22222)
  689. ldi dd16sH,high(-22222)
  690. ldi dv16sL,low(10)
  691. ldi dv16sH,high(10)
  692. rcall div16s ;result: $f752 (-2222)
  693. ;remainder: $0002 (2)
  694.  
  695. forever:rjmp forever
  696. ;----------------------------------
  697. test_slashMod:
  698. ldi r16,$12
  699. mypush r16
  700. ldi r16,$34
  701. mypush r16
  702. ldi r16,$56 ;NB this is $3412 not $1234
  703. mypush r16
  704. ldi r16,$00
  705. mypush r16
  706. rcall slashMod ;$3412 / $56 = $9b rem 0 works
  707. tslm: rjmp tslm
  708.  
  709. ;---------------------------------------
  710. ;From http://www.avr-asm-tutorial.net/avr_en/calc/CONVERT.html#hex2bin
  711. ; Hex4ToBin2
  712. ; converts a 4-digit-hex-ascii to a 16-bit-binary
  713. ; In: Z points to first digit of a Hex-ASCII-coded number
  714. ; Out: T-flag has general result:
  715. ; T=0: rBin1H:L has the 16-bit-binary result, Z points
  716. ; to the first digit of the Hex-ASCII number
  717. ; T=1: illegal character encountered, Z points to the
  718. ; first non-hex-ASCII character
  719. ; Used registers: rBin1H:L (result), R0 (restored after
  720. ; use), rmp
  721. ; Called subroutines: Hex2ToBin1, Hex1ToBin1
  722.  
  723. .def rBin1H =r17
  724. .def rBin1L = r16
  725. .def rmp = r18
  726. ;
  727. Hex4ToBin2:
  728. clt ; Clear error flag
  729. rcall Hex2ToBin1 ; convert two digits hex to Byte
  730. brts Hex4ToBin2a ; Error, go back
  731. mov rBin1H,rmp ; Byte to result MSB
  732. rcall Hex2ToBin1 ; next two chars
  733. brts Hex4ToBin2a ; Error, go back
  734. mov rBin1L,rmp ; Byte to result LSB
  735. sbiw ZL,4 ; result ok, go back to start
  736. Hex4ToBin2a:
  737. ret
  738. ;
  739. ; Hex2ToBin1 converts 2-digit-hex-ASCII to 8-bit-binary
  740. ; Called By: Hex4ToBin2
  741. ;
  742. Hex2ToBin1:
  743. push R0 ; Save register
  744. rcall Hex1ToBin1 ; Read next char
  745. brts Hex2ToBin1a ; Error
  746. swap rmp; To upper nibble
  747. mov R0,rmp ; interim storage
  748. rcall Hex1ToBin1 ; Read another char
  749. brts Hex2ToBin1a ; Error
  750. or rmp,R0 ; pack the two nibbles together
  751. Hex2ToBin1a:
  752. pop R0 ; Restore R0
  753. ret ; and return
  754. ;
  755. ; Hex1ToBin1 reads one char and converts to binary
  756. ;
  757. Hex1ToBin1:
  758. ld rmp,z+ ; read the char
  759. subi rmp,'0' ; ASCII to binary
  760. brcs Hex1ToBin1b ; Error in char
  761. cpi rmp,10 ; A..F
  762. brcs Hex1ToBin1c ; not A..F
  763. cpi rmp,$30 ; small letters?
  764. brcs Hex1ToBin1a ; No
  765. subi rmp,$20 ; small to capital letters
  766. Hex1ToBin1a:
  767. subi rmp,7 ; A..F
  768. cpi rmp,10 ; A..F?
  769. brcs Hex1ToBin1b ; Error, is smaller than A
  770. cpi rmp,16 ; bigger than F?
  771. brcs Hex1ToBin1c ; No, digit ok
  772. Hex1ToBin1b: ; Error
  773. sbiw ZL,1 ; one back
  774. set ; Set flag
  775. Hex1ToBin1c:
  776. ret ; Return
  777. ;--------------------------------------
  778. test_Hex4ToBin2:
  779. pushz
  780. ldi zl,$60
  781. clr zh ;z now points to start of buf1
  782. ldi r16,'0'
  783. st z+,r16
  784. ldi r16,'f'
  785. st z+,r16
  786. ldi r16,'2'
  787. st z+,r16
  788. ldi r16,'3'
  789. st z+,r16
  790. ldi zl,$60
  791. clr zh ;z now points back to start of buf1
  792. rcall Hex4ToBin2
  793. popz
  794. th4: rjmp th4
  795. ;-------------------------------------
  796. numberh: ;word not in dictionary. Try to convert it to hex.
  797. pushz ;algorithm uses z, pity
  798. movw zl,r24 ;r4,25 = w holds start of current word
  799. ;z now points eg to '12ab'start. If t=0 then it coverts to real hex
  800. rcall hex4ToBin2 ;try to convert
  801. ;above call needs 4 hex digits to emerge with t=0 and binary in r16,17
  802. ;want this. If t=0 stack r16,17 and carry on interpreting, else emerge with
  803. ; t=1 and zpointing to first problem char
  804. brtc gotHex
  805. ; if here there's a problem that z is pointing to. Bail out of interpret line
  806. clr STOP
  807. inc STOP
  808. rjmp outnh
  809.  
  810. gotHex: ;sucess.Real hex in r16,17
  811. mypush2 r16,r17 ; so push num onto mystack
  812. outnh:
  813. popz ; but will it be pointing to "right"place in buf1?
  814.  
  815. ret
  816. ; numberh not working fully, ie doesn't point to right place after action.
  817. ; also no action if not a number? TODO better save this first.
Advertisement
Add Comment
Please, Sign In to add comment