2
0

sectorlisp.S 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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 960 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 400
  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 SYNTAX 0x4000
  36. #define LOOK 0x4100
  37. #define GLOBALS 0x4102
  38. #define INDEX 0x4104
  39. #define TOKEN 0x4106
  40. #define STR 0x41c8
  41. ////////////////////////////////////////////////////////////////////////////////
  42. .section .start,"ax",@progbits
  43. .globl main
  44. .code16
  45. main: mov $SYNTAX,%bx
  46. movb $32,32(%bx)
  47. movb $32,13(%bx)
  48. movb $32,10(%bx)
  49. movw $10536,40(%bx)
  50. movb $46,46(%bx)
  51. mov $STR,%di
  52. mov $kSymbols,%si
  53. mov $57,%cx
  54. rep movsb
  55. 0: call GetChar
  56. mov %ax,LOOK
  57. call GetToken
  58. call GetObject
  59. xchg %ax,%di
  60. mov GLOBALS,%si
  61. call Eval
  62. xchg %ax,%di
  63. call PrintObject
  64. mov $kCrlf,%di
  65. call PrintString
  66. jmp 0b
  67. PutChar:push %bx
  68. push %bp # original ibm pc scroll up bug
  69. mov $0x0007,%bx # normal mda/cga style page zero
  70. xchg %di,%ax # character to display
  71. mov $0x0E,%ah # teletype output
  72. int $0x10 # vidya service
  73. pop %bp # result dil→al
  74. pop %bx
  75. ret
  76. GetChar:xor %ax,%ax # get keystroke
  77. int $0x16 # keyboard service
  78. xor %ah,%ah # ah is bios scancode
  79. push %ax # al is ascii character
  80. xchg %ax,%di # result is ax
  81. call PutChar
  82. cmp $'\r,%al
  83. jne 1f
  84. mov $'\n,%di
  85. call PutChar
  86. 1: pop %ax
  87. ret
  88. PrintString:
  89. mov %di,%dx
  90. 0: mov %dx,%di
  91. mov (%di),%al
  92. test %al,%al
  93. je 1f
  94. xchg %ax,%di
  95. call PutChar
  96. inc %dx
  97. jmp 0b
  98. 1: ret
  99. GetToken:
  100. xor %bx,%bx
  101. mov $SYNTAX,%si
  102. mov LOOK,%ax
  103. mov $TOKEN,%cx
  104. 0: mov %al,%bl
  105. mov (%bx,%si),%dl
  106. mov %dl,%bl
  107. cmp $0x20,%dl
  108. jne 1f
  109. call GetChar
  110. jmp 0b
  111. 1: test %dl,%dl
  112. je 3f
  113. xchg %cx,%di
  114. stosb
  115. xchg %di,%cx
  116. call GetChar
  117. jmp 4f
  118. 2: test %bl,%bl
  119. jne 4f
  120. xchg %cx,%di
  121. stosb
  122. xchg %di,%cx
  123. call GetChar
  124. mov %ax,%bx
  125. mov (%bx,%si),%bl
  126. 3: test %al,%al
  127. jne 2b
  128. 4: mov %cx,%di
  129. movb $0,(%di)
  130. mov %al,LOOK
  131. ret
  132. Assoc: xchg %si,%bx
  133. 0: test %bx,%bx
  134. je 2f
  135. and $-2,%bx
  136. mov (%bx),%si
  137. and $-2,%si
  138. mov (%si),%ax
  139. cmp %di,%ax
  140. jne 1f
  141. mov (%bx),%si
  142. and $-2,%si
  143. mov 2(%si),%ax
  144. ret
  145. 1: mov 2(%bx),%bx
  146. jmp 0b
  147. 2: xor %ax,%ax
  148. ret
  149. GetObject:
  150. cmpb $40,TOKEN
  151. je 1f
  152. mov $TOKEN,%di
  153. jmp Intern
  154. 1: #jmp GetList
  155. / 𝑠𝑙𝑖𝑑𝑒
  156. GetList:call GetToken
  157. mov TOKEN,%al
  158. cmp $'),%al
  159. je 2f
  160. cmp $'.,%al
  161. je 1f
  162. call GetObject
  163. push %ax
  164. call GetList
  165. xchg %ax,%si
  166. pop %di
  167. jmp Cons
  168. 1: call GetToken
  169. jmp GetObject
  170. 2: xor %ax,%ax
  171. ret
  172. EvalCons:
  173. push %dx # save
  174. mov 2(%bx),%bx
  175. mov %bx,%di
  176. call Cadr
  177. mov %ax,%di
  178. mov %bp,%si
  179. call Eval
  180. mov %bp,%si
  181. pop %di # restore
  182. push %ax # save
  183. call Arg1
  184. pop %si # restore
  185. xchg %ax,%di
  186. pop %bp
  187. / jmp Cons
  188. / 𝑠𝑙𝑖𝑑𝑒
  189. Cons: mov $INDEX,%bx
  190. mov (%bx),%ax
  191. addw $2,(%bx)
  192. shl %ax
  193. mov %ax,%bx
  194. mov %di,(%bx)
  195. mov %si,2(%bx)
  196. or $1,%ax
  197. ret
  198. Bind: test %di,%di
  199. je 1f
  200. push %bp
  201. mov %sp,%bp
  202. push %dx
  203. push %dx
  204. xchg %si,%bx
  205. and $-2,%bx
  206. and $-2,%di
  207. mov %di,-4(%bp)
  208. mov 2(%bx),%si
  209. mov 2(%di),%di
  210. push %bx # save no. 1
  211. call Bind
  212. pop %bx # rest no. 1
  213. push %ax # save no. 2
  214. mov (%bx),%bx
  215. mov %bx,%di
  216. mov -2(%bp),%si
  217. call Eval
  218. mov -4(%bp),%di
  219. mov (%di),%di
  220. xchg %ax,%si
  221. call Cons
  222. pop %si # rest no. 2
  223. xchg %ax,%di
  224. leave
  225. jmp Cons
  226. 1: xchg %dx,%ax
  227. ret
  228. EvalCdr:
  229. mov %dx,%di
  230. mov %bp,%si
  231. call Arg1
  232. and $-2,%ax
  233. mov %ax,%di
  234. mov 2(%di),%ax
  235. pop %bp
  236. ret
  237. ////////////////////////////////////////////////////////////////////////////////
  238. .text
  239. Cadr: and $-2,%di # (object >> 1) * sizeof(word)
  240. mov 2(%di),%di # contents of decrement register
  241. and $-2,%di # contents of address register
  242. mov (%di),%ax
  243. ret
  244. Arg1: call Cadr
  245. xchg %ax,%di
  246. jmp Eval
  247. PrintObject:
  248. push %bp
  249. mov %di,%bp
  250. test $1,%di
  251. setz %al
  252. shr %di
  253. test %al,%al
  254. je 1f
  255. add $STR,%di
  256. pop %bp
  257. jmp PrintString
  258. 1: mov $40,%di
  259. call PutChar
  260. 2: mov %bp,%bx
  261. and $-2,%bx
  262. mov (%bx),%di
  263. call PrintObject
  264. mov %bp,%bx
  265. and $-2,%bx
  266. mov 2(%bx),%bx
  267. mov %bx,%bp
  268. test %bx,%bx
  269. je 4f
  270. test $1,%bl
  271. je 3f
  272. mov $0x20,%di
  273. call PutChar
  274. jmp 2b
  275. 3: mov $kDot,%di
  276. call PrintString
  277. mov %bp,%di
  278. call PrintObject
  279. 4: mov $41,%di
  280. pop %bp
  281. jmp PutChar
  282. Eval: push %bp
  283. mov %di,%dx
  284. mov %si,%bp
  285. 0: test $1,%dl
  286. jne 1f
  287. xchg %bp,%si
  288. xchg %dx,%di
  289. pop %bp
  290. jmp Assoc
  291. 1: mov %dx,%bx
  292. and $-2,%bx
  293. mov (%bx),%ax
  294. test $1,%al
  295. je 1f
  296. mov (%bx),%ax
  297. and $-2,%ax
  298. mov %ax,%di
  299. mov (%di),%ax
  300. cmp $ATOM_LAMBDA,%ax
  301. jne EvalUndefined
  302. mov 2(%bx),%si
  303. mov (%bx),%di
  304. push %bx
  305. call Cadr
  306. mov %si,%si
  307. mov %ax,%di
  308. mov %bp,%dx
  309. call Bind
  310. mov %ax,%bp
  311. pop %bx
  312. mov (%bx),%bx
  313. mov %bx,%di
  314. and $-2,%di
  315. mov 2(%di),%di
  316. jmp 8f
  317. 1: mov (%bx),%ax
  318. cmp $ATOM_COND,%ax
  319. je EvalCond
  320. jg 2f
  321. cmp $ATOM_ATOM,%ax
  322. je EvalAtom
  323. jg 1f
  324. test %ax,%ax
  325. je EvalUndefined
  326. cmp $ATOM_QUOTE,%ax
  327. jne EvalCall
  328. xchg %dx,%di
  329. pop %bp
  330. jmp Cadr
  331. 1: cmp $ATOM_EQ,%ax
  332. jne EvalCall
  333. push %dx
  334. mov 2(%bx),%bx
  335. mov %bx,%di
  336. call Cadr
  337. mov %ax,%di
  338. mov %bp,%si
  339. call Eval
  340. mov %bp,%si
  341. pop %di # restore
  342. push %ax # save
  343. call Arg1
  344. pop %dx # restore
  345. cmp %dx,%ax
  346. jmp 3f
  347. 2: cmp $ATOM_CDR,%ax
  348. je EvalCdr
  349. cmp $ATOM_CONS,%ax
  350. je EvalCons
  351. cmp $ATOM_CAR,%ax
  352. jne EvalCall
  353. mov %bp,%si
  354. mov %dx,%di
  355. call Arg1
  356. and $-2,%ax
  357. xchg %ax,%di
  358. mov (%di),%ax
  359. jmp 9f
  360. EvalAtom:
  361. mov %bp,%si
  362. mov %dx,%di
  363. call Arg1
  364. test $1,%al
  365. 3: mov $ATOM_T,%ax
  366. je 9f
  367. xor %ax,%ax
  368. jmp 9f
  369. EvalCond:
  370. mov 2(%bx),%bx
  371. mov %bx,%bx
  372. and $-2,%bx
  373. mov (%bx),%di
  374. push %bx # save
  375. and $-2,%di
  376. mov (%di),%di
  377. mov %bp,%si
  378. call Eval
  379. test %ax,%ax
  380. pop %bx # restore
  381. je EvalCond
  382. mov (%bx),%bx
  383. mov %bx,%di
  384. jmp 8f
  385. EvalCall:
  386. mov 2(%bx),%cx
  387. mov (%bx),%bx
  388. mov %bx,%di
  389. mov %bp,%si
  390. call Assoc
  391. mov %cx,%si
  392. mov %ax,%di
  393. call Cons
  394. jmp 1f
  395. 8: call Cadr
  396. 1: mov %ax,%dx
  397. jmp 0b
  398. EvalUndefined:
  399. mov $UNDEFINED,%ax
  400. 9: pop %bp
  401. ret
  402. Intern: push %bp
  403. xchg %di,%bx
  404. mov $STR,%si
  405. 0: lodsb
  406. test %al,%al
  407. je 4f
  408. xor %dx,%dx
  409. 1: mov %dx,%bp
  410. mov %dx,%di
  411. mov (%bx,%di),%cl
  412. cmp %cl,%al
  413. jne 3f
  414. inc %dx
  415. test %al,%al
  416. jne 2f
  417. mov %bp,%cx
  418. sub %cx,%si
  419. lea -STR-1(%si),%ax
  420. jmp 6f
  421. 2: lodsb
  422. jmp 1b
  423. 3: test %al,%al
  424. je 0b
  425. lodsb
  426. jmp 3b
  427. 4: lea -1(%si),%dx
  428. mov %dx,%di
  429. xchg %bx,%si
  430. 0: lodsb
  431. stosb
  432. test %al,%al
  433. jnz 0b
  434. xchg %dx,%ax
  435. sub $STR,%ax
  436. 6: shl %ax
  437. pop %bp
  438. ret
  439. ////////////////////////////////////////////////////////////////////////////////
  440. .section .rodata,"a",@progbits
  441. kDot: .string " . "
  442. kCrlf: .string "\r\n"
  443. kSymbols:
  444. .string "NIL"
  445. .string "*UNDEFINED"
  446. .string "T"
  447. .string "QUOTE"
  448. .string "ATOM"
  449. .string "EQ"
  450. .string "COND"
  451. .string "CAR"
  452. .string "CDR"
  453. .string "CONS"
  454. .string "LAMBDA"
  455. .string ""