GAS LISTING sectorlisp.S 			page 1


 GNU assembler version 2.34 (x86_64-alpine-linux-musl)
	 using BFD version (GNU Binutils) 2.34.
 options passed	: -aghlms=sectorlisp.lst 
 input file    	: sectorlisp.S
 output file   	: sectorlisp.o
 target        	: x86_64-alpine-linux-musl
 time stamp    	: 2021-11-29T10:24:44.000-0800

GAS LISTING sectorlisp.S page 2
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 │ Copyright 2021 Alain Greppin │ 6 │ Some size optimisations by Peter Ferrie │ 7 │ │ 8 │ Permission to use, copy, modify, and/or distribute this software for │ 9 │ any purpose with or without fee is hereby granted, provided that the │ 10 │ above copyright notice and this permission notice appear in all copies. │ 11 │ │ 12 │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ 13 │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ 14 │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ 15 │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ 16 │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ 17 │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ 18 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ 19 │ PERFORMANCE OF THIS SOFTWARE. │ 20 ╚─────────────────────────────────────────────────────────────────────────────*/ 21 22 // LISP meta-circular evaluator in a MBR 23 // Compatible with the original hardware 24 25 .code16 26 .globl _start 27 0000 4E494C00 _start: .asciz "NIL" # dec %si ; dec %cx ; dec %sp 28 0004 5400 kT: .asciz "T" # add %dl,(%si) boot A:\ DL=0 29 0006 EA0000C0 start: ljmp $0x7c00>>4,$begin # cs = 0x7c00 is boot address 29 07 30 000b 00 .asciz "" 31 000c 51554F54 kQuote: .asciz "QUOTE" 31 4500 32 0012 434F4E44 kCond: .asciz "COND" 32 00 33 0017 41544F4D kAtom: .asciz "ATOM" # ordering matters 33 00 34 001c 43415200 kCar: .asciz "CAR" # ordering matters 35 0020 43445200 kCdr: .asciz "CDR" # ordering matters 36 0024 434F4E53 kCons: .asciz "CONS" # ordering matters 36 00 37 0029 455100 kEq: .asciz "EQ" # needs to be last 38 39 002c BC0080 begin: mov $0x8000,%sp # uses higher address as stack 40 # and set independently of SS! 41 # 8088 doesn't stop interrupts 42 # after SS is set, and PC BIOS 43 # sets SP to a value that will 44 # damage our code if int fires 45 # between it setting SS and SP 46 002f 0E push %cs # that means ss = ds = es = cs 47 0030 1F pop %ds # noting ljmp set cs to 0x7c00 48 0031 0E push %cs # that's the bios load address 49 0032 07 pop %es # therefore NULL points to NUL 50 0033 0E push %cs # terminated NIL string above! 51 0034 17 pop %ss # errata exists but don't care 52 0035 BB0200 mov $2,%bx
GAS LISTING sectorlisp.S page 3
53 0038 89E1 main: mov %sp,%cx 54 003a E81100 call GetToken 55 003d E85400 call GetObject 56 0040 E84501 call Eval 57 0043 96 xchg %ax,%si 58 0044 E84300 call PrintObject 59 0047 B00D mov $'\r',%al 60 0049 E87100 call PutChar 61 004c EBEA jmp main 62 63 GetToken: # GetToken():al, dl is g_look 64 004e 89CF mov %cx,%di 65 0050 88D0 1: mov %dl,%al 66 0052 3C20 cmp $' ',%al 67 0054 7602 jbe 2f 68 0056 AA stosb 69 0057 96 xchg %ax,%si 70 0058 E85E00 2: call GetChar # exchanges dx and ax 71 005b 3C20 cmp $' ',%al 72 005d 76F1 jbe 1b 73 005f 3C29 cmp $')',%al 74 0061 7605 jbe 3f 75 0063 80FA29 cmp $')',%dl # dl = g_look 76 0066 77E8 ja 1b 77 0068 883D 3: mov %bh,(%di) # bh is zero 78 006a 96 xchg %si,%ax 79 006b C3 ret 80 81 .PrintList: 82 006c B028 mov $'(',%al 83 006e FF30 2: push (%bx,%si) 84 0070 8B34 mov (%si),%si 85 0072 E81200 call .PutObject 86 0075 B020 mov $' ',%al 87 0077 5E pop %si # restore 1 88 0078 85F6 test %si,%si 89 007a 78F2 js 2b # jump if cons 90 007c 7405 jz 4f # jump if nil 91 007e B0F9 mov $249,%al # bullet (A∙B) 92 0080 E80400 call .PutObject 93 0083 B029 4: mov $')',%al 94 0085 EB36 jmp PutChar 95 96 .PutObject: # .PutObject(c:al,x:si) 97 .PrintString: # nul-terminated in si 98 0087 E83300 call PutChar # preserves si 99 PrintObject: # PrintObject(x:si) 100 008a 85F6 test %si,%si # set sf=1 if cons 101 008c 78DE js .PrintList # jump if not cons 102 .PrintAtom: 103 008e AC lodsb 104 008f 84C0 test %al,%al # test for nul terminator 105 0091 75F4 jnz .PrintString # -> ret 106 0093 C3 ret 107 108 GetObject: # called just after GetToken 109 0094 3C28 cmp $'(',%al
GAS LISTING sectorlisp.S page 4
110 0096 747E je GetList 111 # jmp Intern 112 113 0098 51 Intern: push %cx # Intern(cx,di): ax 114 0099 89FD mov %di,%bp 115 009b 29CD sub %cx,%bp 116 009d 45 inc %bp 117 009e 31FF xor %di,%di 118 00a0 5E 1: pop %si 119 00a1 56 push %si 120 00a2 89E9 mov %bp,%cx 121 00a4 89F8 mov %di,%ax 122 00a6 383D cmp %bh,(%di) 123 00a8 740B je 8f 124 00aa F3A6 rep cmpsb # memcmp(di,si,cx) 125 00ac 7409 je 9f 126 00ae 31C0 xor %ax,%ax 127 00b0 AE 2: scasb # memchr(di,al,cx) 128 00b1 75FD jne 2b 129 00b3 EBEB jmp 1b 130 00b5 F3A4 8: rep movsb # memcpy(di,si,cx) 131 00b7 59 9: pop %cx 132 00b8 C3 ret 133 134 00b9 31C0 GetChar:xor %ax,%ax # GetChar→al:dl 135 00bb CD16 int $0x16 # get keystroke 136 00bd B40E PutChar:mov $0x0e,%ah # prints CP-437 137 00bf CD10 int $0x10 # vidya service 138 00c1 3C0D cmp $'\r',%al # don't clobber 139 00c3 751A jne 1f # look xchg ret 140 00c5 B00A mov $'\n',%al 141 00c7 EBF4 jmp PutChar 142 143 //////////////////////////////////////////////////////////////////////////////// 144 145 00c9 85FF Pairlis:test %di,%di # Pairlis(x:di,y:si,a:dx):ax 146 00cb 7412 jz 1f # jump if nil 147 00cd FF31 push (%bx,%di) # save 1 Cdr(x) 148 00cf AD lodsw 149 00d0 FF34 push (%si) # save 2 Cdr(y) 150 00d2 8B3D mov (%di),%di 151 00d4 E81B00 call Cons # preserves dx 152 00d7 5E pop %si # restore 2 153 00d8 5F pop %di # restore 1 154 00d9 50 push %ax # save 3 155 00da E8ECFF call Pairlis 156 00dd EB12 jmp xCons # can be inlined here 157 00df 92 1: xchg %dx,%ax 158 00e0 C3 ret 159 160 00e1 85FF Evlis: test %di,%di # Evlis(m:di,a:dx):ax 161 00e3 7416 jz 1f # jump if nil 162 00e5 FF31 push (%bx,%di) # save 1 Cdr(m) 163 00e7 8B05 mov (%di),%ax 164 00e9 E89C00 call Eval 165 00ec 5F pop %di # restore 1 166 00ed 50 push %ax # save 2
GAS LISTING sectorlisp.S page 5
167 00ee E8F0FF call Evlis 168 # jmp xCons 169 170 00f1 5F xCons: pop %di # restore 2 171 00f2 87F9 Cons: xchg %di,%cx # Cons(m:di,a:ax):ax 172 00f4 890D mov %cx,(%di) 173 00f6 8901 mov %ax,(%bx,%di) 174 00f8 8D4D04 lea 4(%di),%cx 175 00fb 97 1: xchg %di,%ax 176 00fc C3 ret 177 178 00fd 39D7 Gc: cmp %dx,%di # Gc(x:di,A:dx,B:si):ax 179 00ff 72FA jb 1b # we assume immutable cells 180 0101 FF31 push (%bx,%di) # mark prevents negative gc 181 0103 8B3D mov (%di),%di 182 0105 E8F5FF call Gc 183 0108 5F pop %di 184 0109 50 push %ax 185 010a E8F0FF call Gc 186 010d 5F pop %di 187 010e E8E1FF call Cons 188 0111 29F0 sub %si,%ax # ax -= C - B 189 0113 01D0 add %dx,%ax 190 0115 C3 ret 191 192 0116 E835FF GetList:call GetToken 193 0119 3C29 cmp $')',%al 194 011b 7436 je .retF 195 011d E874FF call GetObject 196 0120 50 push %ax # popped by xCons 197 0121 E8F2FF call GetList 198 0124 EBCB jmp xCons 199 200 0126 56 .dflt1: push %si # save x 201 0127 E85E00 call Eval 202 012a 5E pop %si # restore x 203 # jmp Apply 204 205 012b 85C0 Apply: test %ax,%ax # Apply(fn:ax,x:si:a:dx):ax 206 012d 790D jns .switch # jump if atom 207 012f 97 xchg %ax,%di # di = fn 208 0130 8B39 .lambda:mov (%bx,%di),%di # di = Cdr(fn) 209 0132 57 push %di # save 1 210 0133 8B3D mov (%di),%di # di = Cadr(fn) 211 0135 E891FF call Pairlis 212 0138 92 xchg %ax,%dx 213 0139 5F pop %di # restore 1 214 013a EB49 jmp .EvCadr 215 013c 3D0000 .switch:cmp $kEq,%ax # eq is last builtin atom 216 013f 77E5 ja .dflt1 # ah is zero if not above 217 0141 8B3C mov (%si),%di # di = Car(x) 218 0143 3C00 .ifCar: cmp $kCar,%al 219 0145 742B je Car 220 0147 3C00 .ifCdr: cmp $kCdr,%al 221 0149 7426 je Cdr 222 014b 3C00 .ifAtom:cmp $kAtom,%al 223 014d 7507 jne .ifCons
GAS LISTING sectorlisp.S page 6
224 014f 85FF test %di,%di # test if atom 225 0151 790E jns .retT 226 0153 31C0 .retF: xor %ax,%ax # ax = nil 227 0155 C3 ret 228 0156 3C00 .ifCons:cmp $kCons,%al 229 0158 8B30 mov (%bx,%si),%si # si = Cdr(x) 230 015a AD lodsw # si = Cadr(x) 231 015b 7495 je Cons 232 015d 31F8 .isEq: xor %di,%ax # we know for certain it's eq 233 015f 75F2 jne .retF 234 0161 B000 .retT: mov $kT,%al 235 0163 C3 ret 236 237 0164 89D6 Assoc: mov %dx,%si # Assoc(x:ax,y:dx):ax 238 0166 8B3C 1: mov (%si),%di 239 0168 8B30 mov (%bx,%si),%si 240 016a AF scasw 241 016b 75F9 jne 1b 242 016d F6 .byte 0xF6 # testb §i8,i16(%bp,%di) jmp Car 243 016e 8B39 Cadr: mov (%bx,%di),%di # contents of decrement register 244 0170 3C .byte 0x3C # cmp §scasw,%al (nop next byte) 245 0171 AF Cdr: scasw # increments our data index by 2 246 0172 8B05 Car: mov (%di),%ax # contents of address register!! 247 0174 C3 2: ret 248 249 0175 8B39 1: mov (%bx,%di),%di # di = Cdr(c) 250 0177 57 Evcon: push %di # save c 251 0178 8B35 mov (%di),%si # di = Car(c) 252 017a AD lodsw # ax = Caar(c) 253 017b E80A00 call Eval 254 017e 5F pop %di # restore c 255 017f 85C0 test %ax,%ax # nil test 256 0181 74F2 jz 1b 257 0183 8B3D mov (%di),%di # di = Car(c) 258 0185 E8E6FF .EvCadr:call Cadr # ax = Cadar(c) 259 # jmp Eval 260 261 0188 85C0 Eval: test %ax,%ax # Eval(e:ax,a:dx):ax 262 018a 742B jz 1f 263 018c 79D6 jns Assoc # lookup val if atom 264 018e 96 xchg %ax,%si # di = e 265 018f AD lodsw # ax = Car(e) 266 0190 3D0000 cmp $kQuote,%ax # maybe CONS 267 0193 8B3C mov (%si),%di # di = Cdr(e) 268 0195 74DB je Car 269 0197 3D0000 cmp $kCond,%ax 270 019a 74DB je Evcon # ABC Garbage Collector 271 019c 52 push %dx # save a 272 019d 51 push %cx # save A 273 019e 50 push %ax 274 019f E83FFF call Evlis 275 01a2 96 xchg %ax,%si 276 01a3 58 pop %ax 277 01a4 E884FF call Apply 278 01a7 5A pop %dx # restore A 279 01a8 89CE mov %cx,%si # si = B 280 01aa 97 xchg %ax,%di
GAS LISTING sectorlisp.S page 7
281 01ab E84FFF call Gc 282 01ae 89D7 mov %dx,%di # di = A 283 01b0 29F1 sub %si,%cx # cx = C - B 284 01b2 F3A4 rep movsb 285 01b4 89F9 mov %di,%cx # cx = A + (C - B) 286 01b6 5A pop %dx # restore a 287 01b7 C3 1: ret 288 289 01b8 CECECECE .sig: .fill 512 - (2f - 1f) - (. - _start), 1, 0xce 289 CECECECE 289 CECECECE 289 CECECECE 289 CECECECE 290 01ef 20534543 1: .ascii " SECTORLISP v2 " 290 544F524C 290 49535020 290 763220 291 01fe 55AA .word 0xAA55 292 2: .type .sig,@object 293 .type kQuote,@object 294 .type kCond,@object 295 .type kAtom,@object 296 .type kCar,@object 297 .type kCdr,@object 298 .type kCons,@object 299 .type kEq,@object
GAS LISTING sectorlisp.S page 8
DEFINED SYMBOLS sectorlisp.S:27 .text:0000000000000000 _start sectorlisp.S:28 .text:0000000000000004 kT sectorlisp.S:29 .text:0000000000000006 start sectorlisp.S:39 .text:000000000000002c begin sectorlisp.S:31 .text:000000000000000c kQuote sectorlisp.S:32 .text:0000000000000012 kCond sectorlisp.S:33 .text:0000000000000017 kAtom sectorlisp.S:34 .text:000000000000001c kCar sectorlisp.S:35 .text:0000000000000020 kCdr sectorlisp.S:36 .text:0000000000000024 kCons sectorlisp.S:37 .text:0000000000000029 kEq sectorlisp.S:53 .text:0000000000000038 main sectorlisp.S:63 .text:000000000000004e GetToken sectorlisp.S:108 .text:0000000000000094 GetObject sectorlisp.S:261 .text:0000000000000188 Eval sectorlisp.S:99 .text:000000000000008a PrintObject sectorlisp.S:136 .text:00000000000000bd PutChar sectorlisp.S:134 .text:00000000000000b9 GetChar sectorlisp.S:81 .text:000000000000006c .PrintList sectorlisp.S:96 .text:0000000000000087 .PutObject sectorlisp.S:97 .text:0000000000000087 .PrintString sectorlisp.S:102 .text:000000000000008e .PrintAtom sectorlisp.S:192 .text:0000000000000116 GetList sectorlisp.S:113 .text:0000000000000098 Intern sectorlisp.S:145 .text:00000000000000c9 Pairlis sectorlisp.S:171 .text:00000000000000f2 Cons sectorlisp.S:170 .text:00000000000000f1 xCons sectorlisp.S:160 .text:00000000000000e1 Evlis sectorlisp.S:178 .text:00000000000000fd Gc sectorlisp.S:226 .text:0000000000000153 .retF sectorlisp.S:200 .text:0000000000000126 .dflt1 sectorlisp.S:205 .text:000000000000012b Apply sectorlisp.S:215 .text:000000000000013c .switch sectorlisp.S:208 .text:0000000000000130 .lambda sectorlisp.S:258 .text:0000000000000185 .EvCadr sectorlisp.S:218 .text:0000000000000143 .ifCar sectorlisp.S:246 .text:0000000000000172 Car sectorlisp.S:220 .text:0000000000000147 .ifCdr sectorlisp.S:245 .text:0000000000000171 Cdr sectorlisp.S:222 .text:000000000000014b .ifAtom sectorlisp.S:228 .text:0000000000000156 .ifCons sectorlisp.S:234 .text:0000000000000161 .retT sectorlisp.S:232 .text:000000000000015d .isEq sectorlisp.S:237 .text:0000000000000164 Assoc sectorlisp.S:243 .text:000000000000016e Cadr sectorlisp.S:250 .text:0000000000000177 Evcon sectorlisp.S:289 .text:00000000000001b8 .sig NO UNDEFINED SYMBOLS