sectorlisp.S 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. /*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
  2. │vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
  3. ╞══════════════════════════════════════════════════════════════════════════════╡
  4. │ Copyright 2020 Justine Alexandra Roberts Tunney │
  5. │ │
  6. │ Permission to use, copy, modify, and/or distribute this software for │
  7. │ any purpose with or without fee is hereby granted, provided that the │
  8. │ above copyright notice and this permission notice appear in all copies. │
  9. │ │
  10. │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
  11. │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
  12. │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
  13. │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
  14. │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
  15. │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
  16. │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
  17. │ PERFORMANCE OF THIS SOFTWARE. │
  18. ╚─────────────────────────────────────────────────────────────────────────────*/
  19. // @fileoverview lisp.c built for real mode with manual tuning
  20. // binary footprint is approximately 824 bytes, about 40 bytes
  21. // of it is overhead needed to load the second 512-byte sector
  22. // so if we can find a way to reduce the code size another 300
  23. // bytes we can bootstrap the metacircular evaluator in an mbr
  24. #define NIL 0
  25. #define UNDEFINED 8
  26. #define ATOM_T 30
  27. #define ATOM_QUOTE 34
  28. #define ATOM_ATOM 46
  29. #define ATOM_EQ 56
  30. #define ATOM_COND 62
  31. #define ATOM_CAR 72
  32. #define ATOM_CDR 80
  33. #define ATOM_CONS 88
  34. #define ATOM_LAMBDA 98
  35. #define STR 0x4186
  36. ////////////////////////////////////////////////////////////////////////////////
  37. .section .start,"ax",@progbits
  38. .globl main
  39. .code16
  40. main: mov $q.syntax,%bx
  41. mov $32,%al
  42. mov %al,32(%bx)
  43. mov %al,13(%bx)
  44. mov %al,10(%bx)
  45. movw $10536,40(%bx)
  46. movb $46,46(%bx)
  47. mov $STR,%di
  48. mov $kSymbols,%si
  49. mov $56,%cx
  50. rep movsb
  51. 0: call GetChar
  52. mov %ax,q.look
  53. call GetToken
  54. call GetObject
  55. xchg %ax,%di
  56. mov q.globals,%si
  57. call Eval
  58. xchg %ax,%di
  59. call PrintObject
  60. mov $kCrlf,%si
  61. call PrintString
  62. jmp 0b
  63. GetChar:xor %ax,%ax # get keystroke
  64. int $0x16 # keyboard service
  65. xor %ah,%ah # ah is bios scancode
  66. push %ax # al is ascii character
  67. call PutChar # ax will have result
  68. cmp $'\r',%al # don't clobber stuff
  69. jne 1f
  70. mov $'\n',%al
  71. call PutChar
  72. 1: pop %ax
  73. ret
  74. Cadr: and $-2,%di # (object >> 1) * sizeof(word)
  75. mov 2(%di),%di # contents of decrement register
  76. and $-2,%di # contents of address register
  77. mov (%di),%ax
  78. ret
  79. GetToken:
  80. xor %bx,%bx
  81. mov $q.syntax,%si
  82. mov q.look,%ax
  83. mov $q.token,%di
  84. 0: mov %al,%bl
  85. mov (%bx,%si),%dl
  86. mov %dl,%bl
  87. cmp $0x20,%dl
  88. jne 1f
  89. call GetChar
  90. jmp 0b
  91. 1: test %dl,%dl
  92. je 3f
  93. stosb
  94. call GetChar
  95. jmp 4f
  96. 2: test %bl,%bl
  97. jne 4f
  98. stosb
  99. call GetChar
  100. mov %ax,%bx
  101. mov (%bx,%si),%bl
  102. 3: test %al,%al
  103. jne 2b
  104. 4: movb $0,(%di)
  105. mov %al,q.look
  106. ret
  107. Assoc: xchg %si,%bx
  108. 0: test %bx,%bx
  109. je 2f
  110. and $-2,%bx
  111. mov (%bx),%si
  112. and $-2,%si
  113. mov (%si),%ax
  114. cmp %di,%ax
  115. jne 1f
  116. mov (%bx),%si
  117. and $-2,%si
  118. mov 2(%si),%ax
  119. ret
  120. 1: mov 2(%bx),%bx
  121. jmp 0b
  122. 2: xor %ax,%ax
  123. ret
  124. GetObject:
  125. cmpb $40,q.token
  126. je GetList
  127. mov $q.token,%di
  128. // 𝑠𝑙𝑖𝑑𝑒
  129. Intern: mov %di,%bx
  130. mov $STR,%si
  131. 0: mov %bx,%di
  132. push %si
  133. lodsb
  134. test %al,%al
  135. jne 2f
  136. pop %di
  137. push %di
  138. mov %bx,%si
  139. 4: lodsb
  140. stosb
  141. test %al,%al
  142. jnz 4b
  143. 6: pop %ax
  144. sub $STR,%ax
  145. shl %ax
  146. ret
  147. 1: lodsb
  148. 2: scasb
  149. jne 5f
  150. test %al,%al
  151. jne 1b
  152. jmp 6b
  153. 5: pop %di
  154. 3: test %al,%al
  155. jz 0b
  156. lodsb
  157. jmp 3b
  158. GetList:call GetToken
  159. mov q.token,%al
  160. cmp $')',%al
  161. je 2f
  162. cmp $'.',%al
  163. je 1f
  164. call GetObject
  165. push %ax # save
  166. call GetList
  167. xchg %ax,%si
  168. pop %di # restore
  169. jmp Cons
  170. 1: call GetToken
  171. jmp GetObject
  172. 2: xor %ax,%ax
  173. ret
  174. EvalCons:
  175. push %dx # save
  176. mov 2(%bx),%bx
  177. mov %bx,%di
  178. call Cadr
  179. xchg %ax,%di
  180. mov %bp,%si
  181. call Eval
  182. mov %bp,%si
  183. pop %di # restore
  184. push %ax # save
  185. call Arg1
  186. pop %si # restore
  187. xchg %ax,%di
  188. pop %bp
  189. // jmp Cons
  190. // 𝑠𝑙𝑖𝑑𝑒
  191. Cons: mov $q.index,%bx
  192. mov (%bx),%ax
  193. addw $2,(%bx)
  194. shl %ax
  195. mov %ax,%bx
  196. mov %di,(%bx)
  197. mov %si,2(%bx)
  198. or $1,%ax
  199. ret
  200. Bind: test %di,%di
  201. je 1f
  202. push %bp
  203. and $-2,%si
  204. and $-2,%di
  205. mov %di,%bp
  206. push %dx # save no. 1
  207. push %si # save no. 2
  208. mov 2(%si),%si
  209. mov 2(%di),%di
  210. call Bind
  211. pop %si # rest no. 2
  212. mov (%si),%di
  213. pop %si # rest no. 1
  214. push %ax # save no. 3
  215. call Eval
  216. mov %ds:(%bp),%di
  217. xchg %ax,%si
  218. call Cons
  219. pop %si # rest no. 3
  220. xchg %ax,%di
  221. pop %bp
  222. jmp Cons
  223. 1: xchg %dx,%ax
  224. ret
  225. PrintString: # nul-terminated in si
  226. 0: lodsb # don't clobber bp, bx
  227. test %al,%al
  228. je 1f
  229. call PutChar
  230. jmp 0b
  231. 1: ret
  232. PutChar:push %bx # don't clobber bp,bx,di,si,cx
  233. push %bp # original ibm pc scroll up bug
  234. mov $7,%bx # normal mda/cga style page zero
  235. mov $0x0e,%ah # teletype output al cp437
  236. int $0x10 # vidya service
  237. pop %bp # preserves al
  238. pop %bx
  239. ret
  240. ////////////////////////////////////////////////////////////////////////////////
  241. .text
  242. PrintObject:
  243. test $1,%di
  244. jnz 1f
  245. shr %di
  246. lea STR(%di),%si
  247. jmp PrintString
  248. 1: push %bx
  249. mov %di,%bx
  250. mov $40,%al
  251. call PutChar
  252. 2: and $-2,%bx
  253. mov (%bx),%di
  254. call PrintObject
  255. mov 2(%bx),%bx
  256. test %bx,%bx
  257. jz 4f
  258. test $1,%bl
  259. jz 3f
  260. mov $0x20,%al
  261. call PutChar
  262. jmp 2b
  263. 3: mov $kDot,%si
  264. call PrintString
  265. mov %bx,%di
  266. call PrintObject
  267. 4: pop %bx
  268. mov $41,%al
  269. // jmp PutChar
  270. // 𝑠𝑙𝑖𝑑𝑒
  271. Arg1ds: mov %dx,%di
  272. mov %bp,%si
  273. // 𝑠𝑙𝑖𝑑𝑒
  274. Arg1: call Cadr
  275. xchg %ax,%di
  276. // jmp Eval
  277. // 𝑠𝑙𝑖𝑑𝑒
  278. Eval: push %bp
  279. mov %di,%dx
  280. mov %si,%bp
  281. 0: test $1,%dl
  282. jne 1f
  283. xchg %bp,%si
  284. xchg %dx,%di
  285. pop %bp
  286. jmp Assoc
  287. 1: mov %dx,%bx
  288. and $-2,%bx
  289. mov (%bx),%ax
  290. test $1,%al
  291. je 1f
  292. mov (%bx),%di
  293. and $-2,%di
  294. cmpw $ATOM_LAMBDA,(%di)
  295. jne EvalUndefined
  296. mov 2(%bx),%si
  297. mov (%bx),%di
  298. push %bx
  299. call Cadr
  300. xchg %ax,%di
  301. mov %bp,%dx
  302. call Bind
  303. xchg %ax,%bp
  304. pop %bx
  305. mov (%bx),%bx
  306. mov %bx,%di
  307. and $-2,%di
  308. mov 2(%di),%di
  309. jmp EvalCadrLoop
  310. 1: mov (%bx),%ax
  311. cmp $ATOM_COND,%ax
  312. je EvalCond
  313. jg 2f
  314. cmp $ATOM_ATOM,%ax
  315. je EvalAtom
  316. jg 1f
  317. test %ax,%ax
  318. je EvalUndefined
  319. cmp $ATOM_QUOTE,%ax
  320. jne EvalCall
  321. // 𝑠𝑙𝑖𝑑𝑒
  322. EvalQuote:
  323. xchg %dx,%di
  324. pop %bp
  325. jmp Cadr
  326. 1: cmp $ATOM_EQ,%ax
  327. jne EvalCall
  328. // 𝑠𝑙𝑖𝑑𝑒
  329. EvalEq: push %dx
  330. mov 2(%bx),%bx
  331. mov %bx,%di
  332. call Cadr
  333. xchg %ax,%di
  334. mov %bp,%si
  335. call Eval
  336. mov %bp,%si
  337. pop %di # restore
  338. push %ax # save
  339. call Arg1
  340. pop %dx # restore
  341. cmp %dx,%ax
  342. jmp 3f
  343. EvalCdr:
  344. push $2
  345. jmp EvalCarCdr
  346. EvalUndefined:
  347. mov $UNDEFINED,%ax
  348. 9: pop %bp
  349. ret
  350. EvalCond:
  351. mov 2(%bx),%bx
  352. and $-2,%bx
  353. mov (%bx),%di
  354. and $-2,%di
  355. mov (%di),%di
  356. mov %bp,%si
  357. push %bx # save
  358. call Eval
  359. pop %bx # restore
  360. test %ax,%ax
  361. je EvalCond
  362. mov (%bx),%di
  363. jmp EvalCadrLoop
  364. 2: cmp $ATOM_CDR,%ax
  365. je EvalCdr
  366. cmp $ATOM_CONS,%ax
  367. je EvalCons
  368. cmp $ATOM_CAR,%ax
  369. jne EvalCall
  370. // 𝑠𝑙𝑖𝑑𝑒
  371. EvalCar:
  372. push $0
  373. // 𝑠𝑙𝑖𝑑𝑒
  374. EvalCarCdr:
  375. call Arg1ds
  376. and $-2,%ax
  377. xchg %ax,%di
  378. pop %bx
  379. mov (%bx,%di),%ax
  380. jmp 9b
  381. EvalCall:
  382. push 2(%bx)
  383. mov (%bx),%di
  384. mov %bp,%si
  385. call Assoc
  386. xchg %ax,%di
  387. pop %si
  388. call Cons
  389. jmp 1f
  390. EvalAtom:
  391. call Arg1ds
  392. test $1,%al
  393. 3: mov $ATOM_T,%ax
  394. je 9b
  395. xor %ax,%ax
  396. jmp 9b
  397. EvalCadrLoop:
  398. call Cadr
  399. 1: xchg %ax,%dx
  400. jmp 0b
  401. ////////////////////////////////////////////////////////////////////////////////
  402. .section .rodata,"a",@progbits
  403. kDot: .string " . "
  404. kCrlf: .string "\r\n"
  405. kSymbols:
  406. .string "NIL"
  407. .string "*UNDEFINED"
  408. .string "T"
  409. .string "QUOTE"
  410. .string "ATOM"
  411. .string "EQ"
  412. .string "COND"
  413. .string "CAR"
  414. .string "CDR"
  415. .string "CONS"
  416. .string "LAMBDA"