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 -g input file : sectorlisp.S output file : sectorlisp.o target : x86_64-alpine-linux-musl time stamp : 2021-12-11T00:49:38.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 E84101 call Eval 57 0043 96 xchg %ax,%si 58 0044 E84300 call PrintObject 59 0047 B00D mov $'\r',%al 60 0049 E87200 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 E85F00 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 EB37 jmp PutChar 95 96 .PutObject: # .PutObject(c:al,x:si) 97 .PrintString: # nul-terminated in si 98 0087 E83400 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 7450 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 740C je 8f 124 00aa F3A6 rep cmpsb # memcmp(di,si,cx) 125 00ac 740A je 9f 126 00ae 4F dec %di 127 00af 31C0 xor %ax,%ax 128 00b1 AE 2: scasb # memchr(di,al,cx) 129 00b2 75FD jne 2b 130 00b4 EBEA jmp 1b 131 00b6 F3A4 8: rep movsb # memcpy(di,si,cx) 132 00b8 59 9: pop %cx 133 00b9 C3 ret 134 135 00ba 31C0 GetChar:xor %ax,%ax # GetChar→al:dl 136 00bc CD16 int $0x16 # get keystroke 137 00be B40E PutChar:mov $0x0e,%ah # prints CP-437 138 00c0 CD10 int $0x10 # vidya service 139 00c2 3C0D cmp $'\r',%al # don't clobber 140 00c4 7504 jne 1f # look xchg ret 141 00c6 B00A mov $'\n',%al 142 00c8 EBF4 jmp PutChar 143 00ca 92 1: xchg %dx,%ax 144 00cb C3 ret 145 146 //////////////////////////////////////////////////////////////////////////////// 147 148 00cc 85FF Evlis: test %di,%di # Evlis(m:di,a:dx):ax 149 00ce 7416 jz 1f # jump if nil 150 00d0 FF31 push (%bx,%di) # save 1 Cdr(m) 151 00d2 8B05 mov (%di),%ax 152 00d4 E8AD00 call Eval 153 00d7 5F pop %di # restore 1 154 00d8 50 push %ax # save 2 155 00d9 E8F0FF call Evlis 156 # jmp xCons 157 158 00dc 5F xCons: pop %di # restore 2 159 00dd 87F9 Cons: xchg %di,%cx # Cons(m:di,a:ax):ax 160 00df 890D mov %cx,(%di) # must preserve si 161 00e1 8901 mov %ax,(%bx,%di) 162 00e3 8D4D04 lea 4(%di),%cx 163 00e6 97 1: xchg %di,%ax 164 00e7 C3 ret 165 166 00e8 E863FF GetList:call GetToken GAS LISTING sectorlisp.S page 5 167 00eb 3C29 cmp $')',%al 168 00ed 745F je .retF 169 00ef E8A2FF call GetObject 170 00f2 50 push %ax # popped by xCons 171 00f3 E8F2FF call GetList 172 00f6 EBE4 jmp xCons 173 174 00f8 39D7 Gc: cmp %dx,%di # Gc(x:di,A:dx,B:si):ax 175 00fa 72EA jb 1b # we assume immutable cells 176 00fc FF31 push (%bx,%di) # mark prevents negative gc 177 00fe 8B3D mov (%di),%di 178 0100 E8F5FF call Gc 179 0103 5F pop %di 180 0104 50 push %ax 181 0105 E8F0FF call Gc 182 0108 5F pop %di 183 0109 E8D1FF call Cons 184 010c 29F0 sub %si,%ax # ax -= C - B 185 010e 01D0 add %dx,%ax 186 0110 C3 ret 187 188 0111 56 .dflt1: push %si # save x 189 0112 E86F00 call Eval 190 0115 5E pop %si # restore x 191 # jmp Apply 192 193 0116 85C0 Apply: test %ax,%ax # Apply(fn:ax,x:si:a:dx):ax 194 0118 791D jns .switch # jump if atom 195 011a 97 xchg %ax,%di # di = fn 196 011b 8B39 .lambda:mov (%bx,%di),%di # di = Cdr(fn) 197 011d 57 push %di # for .EvCadr 198 011e 8B3D mov (%di),%di # di = Cadr(fn) 199 0120 85FF Pairlis:test %di,%di # Pairlis(x:di,y:si,a:dx):dx 200 0122 745C jz .EvCadr # return if x is nil 201 0124 AD lodsw # ax = Car(y) 202 0125 FF31 push (%bx,%di) # push Cdr(x) 203 0127 8B3D mov (%di),%di # di = Car(x) 204 0129 8B34 mov (%si),%si # si = Cdr(y) 205 012b E8AFFF call Cons # Cons(Car(x),Car(y)) 206 012e 97 xchg %ax,%di 207 012f 92 xchg %dx,%ax 208 0130 E8AAFF call Cons # Cons(Cons(Car(x),Car(y)),a) 209 0133 92 xchg %ax,%dx # a = new list 210 0134 5F pop %di # grab Cdr(x) 211 0135 EBE9 jmp Pairlis 212 0137 3D0000 .switch:cmp $kEq,%ax # eq is last builtin atom 213 013a 77D5 ja .dflt1 # ah is zero if not above 214 013c 8B3C mov (%si),%di # di = Car(x) 215 013e 3C00 .ifCar: cmp $kCar,%al 216 0140 742B je Car 217 0142 3C00 .ifCdr: cmp $kCdr,%al 218 0144 7426 je Cdr 219 0146 3C00 .ifAtom:cmp $kAtom,%al 220 0148 7507 jne .ifCons 221 014a 85FF test %di,%di # test if atom 222 014c 790E jns .retT 223 014e 31C0 .retF: xor %ax,%ax # ax = nil GAS LISTING sectorlisp.S page 6 224 0150 C3 ret 225 0151 3C00 .ifCons:cmp $kCons,%al 226 0153 8B30 mov (%bx,%si),%si # si = Cdr(x) 227 0155 AD lodsw # si = Cadr(x) 228 0156 7485 je Cons 229 0158 31F8 .isEq: xor %di,%ax # we know for certain it's eq 230 015a 75F2 jne .retF 231 015c B000 .retT: mov $kT,%al 232 015e C3 ret 233 234 015f 89D6 Assoc: mov %dx,%si # Assoc(x:ax,y:dx):ax 235 0161 8B3C 1: mov (%si),%di 236 0163 8B30 mov (%bx,%si),%si 237 0165 AF scasw 238 0166 75F9 jne 1b 239 0168 F6 .byte 0xF6 # testb §i8,i16(%bp,%di) jmp Car 240 0169 8B39 Cadr: mov (%bx,%di),%di # contents of decrement register 241 016b 3C .byte 0x3C # cmp §scasw,%al (nop next byte) 242 016c AF Cdr: scasw # increments our data index by 2 243 016d 8B05 Car: mov (%di),%ax # contents of address register!! 244 016f C3 2: ret 245 246 0170 8B39 1: mov (%bx,%di),%di # di = Cdr(c) 247 0172 57 Evcon: push %di # save c 248 0173 8B35 mov (%di),%si # di = Car(c) 249 0175 AD lodsw # ax = Caar(c) 250 0176 E80B00 call Eval 251 0179 5F pop %di # restore c 252 017a 85C0 test %ax,%ax # nil test 253 017c 74F2 jz 1b 254 017e FF35 push (%di) # push Car(c) 255 0180 5F .EvCadr:pop %di 256 0181 E8E5FF call Cadr # ax = Cadar(c) 257 # jmp Eval 258 259 0184 85C0 Eval: test %ax,%ax # Eval(e:ax,a:dx):ax 260 0186 742B jz 1f 261 0188 79D5 jns Assoc # lookup val if atom 262 018a 96 xchg %ax,%si # di = e 263 018b AD lodsw # ax = Car(e) 264 018c 3D0000 cmp $kQuote,%ax # maybe CONS 265 018f 8B3C mov (%si),%di # di = Cdr(e) 266 0191 74DA je Car 267 0193 3D0000 cmp $kCond,%ax 268 0196 74DA je Evcon # ABC Garbage Collector 269 0198 52 push %dx # save a 270 0199 51 push %cx # save A 271 019a 50 push %ax 272 019b E82EFF call Evlis 273 019e 96 xchg %ax,%si 274 019f 58 pop %ax 275 01a0 E873FF call Apply 276 01a3 5A pop %dx # restore A 277 01a4 89CE mov %cx,%si # si = B 278 01a6 97 xchg %ax,%di 279 01a7 E84EFF call Gc 280 01aa 89D7 mov %dx,%di # di = A GAS LISTING sectorlisp.S page 7 281 01ac 29F1 sub %si,%cx # cx = C - B 282 01ae F3A4 rep movsb 283 01b0 89F9 mov %di,%cx # cx = A + (C - B) 284 01b2 5A pop %dx # restore a 285 01b3 C3 1: ret 286 287 01b4 CECECECE .sig: .fill 512 - (2f - 1f) - (. - _start), 1, 0xce 287 CECECECE 287 CECECECE 287 CECECECE 287 CECECECE 288 01ef 20534543 1: .ascii " SECTORLISP v2 " 288 544F524C 288 49535020 288 763220 289 01fe 55AA .word 0xAA55 290 2: .type .sig,@object 291 .type kQuote,@object 292 .type kCond,@object 293 .type kAtom,@object 294 .type kCar,@object 295 .type kCdr,@object 296 .type kCons,@object 297 .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:259 .text:0000000000000184 Eval sectorlisp.S:99 .text:000000000000008a PrintObject sectorlisp.S:137 .text:00000000000000be PutChar sectorlisp.S:135 .text:00000000000000ba 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:166 .text:00000000000000e8 GetList sectorlisp.S:113 .text:0000000000000098 Intern sectorlisp.S:148 .text:00000000000000cc Evlis sectorlisp.S:158 .text:00000000000000dc xCons sectorlisp.S:159 .text:00000000000000dd Cons sectorlisp.S:223 .text:000000000000014e .retF sectorlisp.S:174 .text:00000000000000f8 Gc sectorlisp.S:188 .text:0000000000000111 .dflt1 sectorlisp.S:193 .text:0000000000000116 Apply sectorlisp.S:212 .text:0000000000000137 .switch sectorlisp.S:196 .text:000000000000011b .lambda sectorlisp.S:199 .text:0000000000000120 Pairlis sectorlisp.S:255 .text:0000000000000180 .EvCadr sectorlisp.S:215 .text:000000000000013e .ifCar sectorlisp.S:243 .text:000000000000016d Car sectorlisp.S:217 .text:0000000000000142 .ifCdr sectorlisp.S:242 .text:000000000000016c Cdr sectorlisp.S:219 .text:0000000000000146 .ifAtom sectorlisp.S:225 .text:0000000000000151 .ifCons sectorlisp.S:231 .text:000000000000015c .retT sectorlisp.S:229 .text:0000000000000158 .isEq sectorlisp.S:234 .text:000000000000015f Assoc sectorlisp.S:240 .text:0000000000000169 Cadr sectorlisp.S:247 .text:0000000000000172 Evcon sectorlisp.S:287 .text:00000000000001b4 .sig NO UNDEFINED SYMBOLS