├── .gitignore ├── LICENSE ├── README ├── basic.asm ├── basic.o ├── bootBASIC_32bit ├── basic.asm ├── basic.o ├── bootbasic └── c.sh ├── bootbasic └── c.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | backup/ 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Oscar Toledo G. http://nanochess.org/ 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | bootBASIC_64bit is an implementation of bootBASIC for macOS by @taisukef 2 | https://fukuno.jig.jp/2853 3 | 4 | also bootBASIC_32bit is an implementation of bootBASIC for macOS by @taisukef 5 | https://fukuno.jig.jp/2729 6 | 7 | 8 | Use this command line on macOS: 9 | sh c.sh 10 | 11 | see also original README of bootBASIC 12 | _ _ ______ ___ _____ _____ _____ 13 | | | | | | ___ \/ _ \ / ___|_ _/ __ \ 14 | | |__ ___ ___ | |_| |_/ / /_\ \\ `--. | | | / \/ 15 | | '_ \ / _ \ / _ \| __| ___ \ _ | `--. \ | | | | 16 | | |_) | (_) | (_) | |_| |_/ / | | |/\__/ /_| |_| \__/\ 17 | |_.__/ \___/ \___/ \__\____/\_| |_/\____/ \___/ \____/ 18 | 19 | bootBASIC interpreter in 512 bytes (boot sector or COM file) 20 | by Oscar Toledo G. Jul/22/2019 21 | 22 | http://nanochess.org 23 | https://github.com/nanochess 24 | 25 | This is an integer BASIC language interpreter. 26 | 27 | It's compatible with the 8088 processor (the original IBM PC). 28 | 29 | If you want to assemble it, you must download the Netwide Assembler 30 | (nasm) from www.nasm.us 31 | 32 | Use this command line: 33 | 34 | nasm -f bin basic.asm -Dcom_file=1 -o basic.com 35 | nasm -f bin basic.asm -Dcom_file=0 -o basic.img 36 | 37 | Tested with VirtualBox for Mac OS X running Windows XP running this 38 | interpreter, it also works with DosBox and probably with qemu: 39 | 40 | qemu-system-x86_64 -fda basic.img 41 | 42 | Enjoy it! 43 | 44 | 45 | _ _ _ __ __ _ 46 | | | | |___ ___ _ _( )___ | \/ |__ _ _ _ _ _ __ _| | 47 | | |_| (_- case insensitive in 64bit) 58 | 59 | Line numbers can be 1 to 999. 60 | 61 | 26 variables are available (a-z) 62 | 63 | Numbers (0-65535) can be entered and display as unsigned. (-> 64bit in 64bit) 64 | 65 | To enter new program lines: 66 | 10 print "Hello, world!" 67 | 68 | To erase program lines: 69 | 10 70 | 71 | To test statements directly (interactive syntax): 72 | print "Hello, world!" 73 | 74 | To erase the current program: 75 | new 76 | 77 | To run the current program: 78 | run 79 | 80 | To list the current program: 81 | list 82 | 83 | To exit to command-line: 84 | system 85 | 86 | Statements: 87 | var=expr Assign expr value to var (a-z) 88 | 89 | print expr Print expression value, new line 90 | print expr; Print expression value, continue 91 | print "hello" Print string, new line 92 | print "hello"; Print string, continue 93 | 94 | input var Input value into variable (a-z) 95 | 96 | goto expr Goto to indicated line in program 97 | 98 | if expr1 goto expr2 99 | If expr1 is non-zero then go to line, 100 | else go to following line. 101 | 102 | Examples of if: 103 | 104 | if c-5 goto 20 If c isn't 5, go to line 20 105 | 106 | Expressions: 107 | 108 | The operators +, -, / and * are available with 109 | common precedence rules and signed operation. 110 | 111 | You can also use parentheses: 112 | 113 | 5+6*(10/2) 114 | 115 | Variables and numbers can be used in expressions. 116 | 117 | Sample program (counting 1 to 10): 118 | 119 | 10 a=1 120 | 20 print a 121 | 30 a=a+1 122 | 40 if a-11 goto 20 123 | 124 | Sample program (Pascal's triangle, each number is the sum 125 | of the two over it): 126 | 127 | 10 input n 128 | 20 i=1 129 | 30 c=1 130 | 40 j=0 131 | 50 t=n-i 132 | 60 if j-t goto 80 133 | 70 goto 110 134 | 80 print " "; 135 | 90 j=j+1 136 | 100 goto 50 137 | 110 k=1 138 | 120 if k-i-1 goto 140 139 | 130 goto 190 140 | 140 print c; 141 | 150 c=c*(i-k)/k 142 | 160 print " "; 143 | 170 k=k+1 144 | 180 goto 120 145 | 190 print 146 | 200 i=i+1 147 | 210 if i-n-1 goto 30 148 | 149 | 150 | >> ATTENTION << 151 | 152 | Do you would like more details on the inner workings? This program 153 | is fully commented in my new book Programming Boot Sector Games 154 | and you'll also find a 8086/8088 crash course! 155 | 156 | Now available from Lulu: 157 | 158 | Soft-cover 159 | http://www.lulu.com/shop/oscar-toledo-gutierrez/programming-boot-sector-games/paperback/product-24188564.html 160 | 161 | Hard-cover 162 | http://www.lulu.com/shop/oscar-toledo-gutierrez/programming-boot-sector-games/hardcover/product-24188530.html 163 | 164 | eBook 165 | https://nanochess.org/store.html 166 | 167 | These are some of the example programs documented profusely 168 | in the book: 169 | 170 | * Guess the number. 171 | * Tic-Tac-Toe game. 172 | * Text graphics. 173 | * Mandelbrot set. 174 | * F-Bird game. 175 | * Invaders game. 176 | * Pillman game. 177 | * Toledo Atomchess. 178 | * bootBASIC language. 179 | 180 | -------------------------------------------------------------------------------- /basic.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; bootBASIC interpreter in 512 bytes (boot sector) 3 | ; 4 | ; by Oscar Toledo G. 5 | ; http://nanochess.org/ 6 | ; 7 | ; (c) Copyright 2019 Oscar Toledo G. 8 | ; 9 | ; Creation date: Jul/19/2019. 10pm to 12am. 10 | ; Revision date: Jul/20/2019. 10am to 2pm. 11 | ; Added assignment statement. list now 12 | ; works. run/goto now works. Added 13 | ; system and new. 14 | ; Revision date: Jul/22/2019. Boot image now includes 'system' 15 | ; statement. 16 | ; 17 | 18 | ; Revision date: Jan/12/2020. Implimentation for macOS(386 32bit) by @taisukef 19 | ; Revision date: May/18/2020. Implimentation for macOS(x64 64bit) by @taisukef 20 | 21 | ; 22 | ; USER'S MANUAL: 23 | ; 24 | ; Line entry is done with keyboard, finish the line with Enter. 25 | ; Only 19 characters per line as maximum. 26 | ; 27 | ; Backspace can be used, don't be fooled by the fact 28 | ; that screen isn't deleted (it's all right in the buffer). 29 | ; 30 | ; All statements must be in lowercase. -> case insensitive in 64bit version 31 | ; 32 | ; Line numbers can be 1 to 999. 33 | ; 34 | ; 26 variables are available (a-z) 35 | ; 36 | ; Numbers (0-65535) can be entered and display as unsigned. 37 | ; 38 | ; To enter new program lines: 39 | ; 10 print "Hello, world!" 40 | ; 41 | ; To erase program lines: 42 | ; 10 43 | ; 44 | ; To test statements directly (interactive syntax): 45 | ; print "Hello, world!" 46 | ; 47 | ; To erase the current program: 48 | ; new 49 | ; 50 | ; To run the current program: 51 | ; run 52 | ; 53 | ; To list the current program: 54 | ; list 55 | ; 56 | ; To exit to command-line: 57 | ; system 58 | ; 59 | ; Statements: 60 | ; var=expr Assign expr value to var (a-z) 61 | ; 62 | ; print expr Print expression value, new line 63 | ; print expr; Print expression value, continue 64 | ; print "hello" Print string, new line 65 | ; print "hello"; Print string, continue 66 | ; 67 | ; input var Input value into variable (a-z) 68 | ; 69 | ; goto expr Goto to indicated line in program 70 | ; 71 | ; if expr1 goto expr2 72 | ; If expr1 is non-zero then go to line, 73 | ; else go to following line. 74 | ; 75 | ; Examples of if: 76 | ; 77 | ; if c-5 goto 20 If c isn't 5, go to line 20 78 | ; 79 | ; Expressions: 80 | ; 81 | ; The operators +, -, / and * are available with 82 | ; common precedence rules and signed operation. 83 | ; 84 | ; You can also use parentheses: 85 | ; 86 | ; 5+6*(10/2) 87 | ; 88 | ; Variables and numbers can be used in expressions. 89 | ; 90 | ; Sample program (counting 1 to 10): 91 | ; 92 | ; 10 a=1 93 | ; 20 print a 94 | ; 30 a=a+1 95 | ; 40 if a-11 goto 20 96 | ; 97 | ; Sample program (Pascal's triangle, each number is the sum 98 | ; of the two over it): 99 | ; 100 | ; 10 input n 101 | ; 20 i=1 102 | ; 30 c=1 103 | ; 40 j=0 104 | ; 50 t=n-i 105 | ; 60 if j-t goto 80 106 | ; 70 goto 110 107 | ; 80 print " "; 108 | ; 90 j=j+1 109 | ; 100 goto 50 110 | ; 110 k=1 111 | ; 120 if k-i-1 goto 140 112 | ; 130 goto 190 113 | ; 140 print c; 114 | ; 150 c=c*(i-k)/k 115 | ; 160 print " "; 116 | ; 170 k=k+1 117 | ; 180 goto 120 118 | ; 190 print 119 | ; 200 i=i+1 120 | ; 210 if i-n-1 goto 30 121 | ; 122 | 123 | ; cpu 8086 ; original 124 | cpu x64 ; for 64bit 125 | 126 | section .text 127 | global _main 128 | 129 | max_line: equ 10000 ; First unavailable line number (org 1000) 130 | max_length: equ 200 ; Maximum length of line (org 20) 131 | max_size: equ max_line * max_length ; Max. program size 132 | 133 | section .bss 134 | vars resb (32 * 8) ; variables 64bit x 32(@,A~Z...) 135 | line resb 1024 ; line input buffer 136 | program resb max_size ; Program memory 137 | 138 | section .text 139 | 140 | 141 | _main: 142 | start: 143 | cld ; Clear Direction flag 144 | mov rdi, program ; Point to program 145 | mov rax, 0x0d ; Fill with CR 146 | mov rcx, max_size ; Max. program size 147 | rep stosb ; Initialize 148 | 149 | ; test code 150 | ; mov rax, 12345678912345678912 ; 64bit output test 151 | ; call output_number 152 | ; call new_line 153 | ; call syscall_exit 154 | ; mov rax, 10000 155 | ; call debug_n 156 | ; call syscall_exit 157 | 158 | ; 159 | ; Main loop 160 | ; 161 | main_loop: 162 | ;mov sp,stack ; Reinitialize stack pointer 163 | mov rax, main_loop 164 | push rax 165 | 166 | xor rax,rax ; Mark as interactive 167 | ;mov [running],rax 168 | mov r10, rax 169 | mov al, '>' ; Show prompt 170 | call input_line ; Accept line 171 | call input_number ; Get number 172 | or rax, rax ; No number or zero? 173 | je statement ; Yes, jump 174 | call find_line ; Find the line 175 | or rax, rax 176 | jz main_loop_skip ; line number over 177 | xchg rax, rdi 178 | ; mov cx, max_length ; CX loaded with this value in 'find_line' 179 | rep movsb ; Copy entered line into program 180 | ret 181 | main_loop_skip: 182 | pop rax 183 | jmp error 184 | 185 | ; 186 | ; Handle 'if' statement 187 | ; 188 | if_statement: 189 | call expr ; Process expression 190 | or rax, rax ; Is it zero? 191 | je f6 ; Yes, return (ignore if) 192 | statement: 193 | call spaces ; Avoid spaces 194 | cmp byte [rsi], 0x0d ; Empty line? 195 | je f6 ; Yes, return 196 | mov rdi, statements ; Point to statements list 197 | mov r11, statements_func 198 | f5: xor rax, rax 199 | mov al, [rdi] ; Read length of the string 200 | inc rdi ; Avoid length byte 201 | and ax, 0x00ff ; Is it zero? 202 | je f4 ; Yes, jump 203 | xchg rax, rcx 204 | push rsi ; Save current position 205 | 206 | ; Compare statement (rsi, rdi, length:rcx) 207 | 208 | ; case sensitive check (original) 209 | ; rep cmpsb 210 | ; jne statement_not_match ; Equal? No, jump 211 | 212 | ; case insensitive check 213 | statement_check: 214 | mov al, [rdi] 215 | and al, 0xdf 216 | mov ah, [rsi] 217 | and ah, 0xdf 218 | cmp al, ah 219 | jne statement_not_match 220 | inc rdi 221 | inc rsi 222 | dec rcx 223 | jnz statement_check 224 | statement_check_end: 225 | 226 | pop rax 227 | call spaces ; Avoid spaces 228 | jmp [r11] ; Jump to process statement 229 | 230 | statement_not_match: 231 | add rdi, rcx ; Advance the list pointer 232 | add r11, 8 ; next func 233 | pop rsi 234 | jmp f5 ; Compare another statement 235 | 236 | f4: call get_variable ; Try variable 237 | push rax ; Save address 238 | lodsb ; Read a line letter 239 | cmp al, '=' ; Is it assignment '=' ? 240 | je assignment ; Yes, jump to assignment. 241 | 242 | ; 243 | ; An error happened 244 | ; 245 | error: 246 | mov rsi, error_message 247 | call print_2 ; Show error message 248 | jmp main_loop ; Exit to main loop 249 | 250 | error_message: 251 | ; db "@#!",0x0d ; Guess the words :P 252 | db "Syntax error", 0x0d 253 | 254 | ; 255 | ; Handle 'list' statement 256 | ; 257 | list_statement: 258 | xor rax, rax ; Start from line zero 259 | f29: push rax 260 | call find_line ; Find program line 261 | xchg rax, rsi 262 | cmp byte [rsi], 0x0d ; Empty line? 263 | je f30 ; Yes, jump 264 | pop rax 265 | push rax 266 | call output_number ; Show line number 267 | f32: lodsb ; Show line contents 268 | call output 269 | jne f32 ; Jump if it wasn't 0x0d (CR) 270 | f30: pop rax 271 | inc rax ; Go to next line 272 | cmp rax, max_line ; Finished? 273 | jne f29 ; No, continue 274 | f6: 275 | ret 276 | 277 | ; 278 | ; Handle 'input' statement 279 | ; 280 | input_statement: 281 | call get_variable ; Get variable address 282 | push rax ; Save it 283 | mov al, '?' ; Prompt 284 | call input_line ; Wait for line 285 | ; 286 | ; Second part of the assignment statement 287 | ; 288 | assignment: 289 | call expr ; Process expression 290 | pop rdi 291 | mov [rdi], rax ; save onto variable 64bit 292 | ret 293 | 294 | ; Handle an expression. 295 | ; First tier: addition & subtraction. 296 | expr: 297 | call expr1 ; Call second tier 298 | f20: cmp byte [rsi], '-' ; Subtraction operator? 299 | je f19 ; Yes, jump 300 | cmp byte [rsi], '+' ; Addition operator? 301 | je f20_2 302 | ret 303 | f20_2: 304 | push rax 305 | call expr1_2 ; Call second tier 306 | f15: pop rcx 307 | add rax, rcx ; Addition 308 | jmp f20 ; Find more operators 309 | f19: 310 | push rax 311 | call expr1_2 ; Call second tier 312 | neg rax ; Negate it (a - b converted to a + -b) 313 | jmp f15 314 | 315 | ; 316 | ; Handle an expression. 317 | ; Second tier: division & multiplication. 318 | ; 319 | expr1_2: 320 | inc rsi ; Avoid operator 321 | expr1: 322 | call expr2 ; Call third tier 323 | f21: cmp byte [rsi], '/' ; Division operator? 324 | je f23 ; Yes, jump 325 | cmp byte [rsi], '*' ; Multiplication operator? 326 | jne f6 ; No, return 327 | 328 | push rax 329 | call expr2_2 ; Call third tier 330 | pop rcx 331 | imul rcx ; Multiplication 332 | jmp f21 ; Find more operators 333 | 334 | f23: 335 | push rax 336 | call expr2_2 ; Call third tier 337 | pop rcx 338 | cmp rax, 0 339 | jz expr1_div0 340 | xchg rax, rcx 341 | ; cwd ; Expand AX to DX:AX 342 | ;idiv rcx ; Signed division 343 | cqo ; Expand RAX to RDX:RAX 344 | idiv rcx ; singned division RDX:RAX / RCX = RAX (... RDX) 345 | jmp f21 ; Find more operators 346 | expr1_div0: 347 | mov rax, 0 348 | jmp f21 349 | 350 | ; 351 | ; Handle an expression. 352 | ; Third tier: parentheses, numbers and vars. 353 | ; 354 | expr2_2: 355 | inc rsi ; Avoid operator 356 | expr2: 357 | call spaces ; Jump spaces 358 | lodsb ; Read character 359 | cmp al, '(' ; Open parenthrsis? 360 | jne f24 361 | call expr ; Process inner expr. 362 | cmp byte [rsi], ')' ; Closing parenthrsis? 363 | je spaces_2 ; Yes, avoid spaces 364 | jmp error ; No, jump to error 365 | 366 | ;cmp al, '-' ; minus? 367 | ;jne f24 368 | ;inc rsi 369 | ;lodsb 370 | ;call f24 371 | ;neg rax 372 | ;mov rax, 30 373 | ;ret 374 | 375 | f24: cmp al, 0x40 ; Variable? 376 | jnc f25 ; Yes, jump 377 | dec rsi ; Back one letter... 378 | call input_number ; ...to read number 379 | jmp spaces ; Avoid spaces 380 | 381 | f25: call get_variable_2 ; Get variable address 382 | xchg rax, rbx 383 | mov rax, [rbx] ; Read 384 | ret ; Return 385 | 386 | ; 387 | ; Get variable address 388 | ; 389 | get_variable: 390 | xor rax, rax ; rax = 0 391 | lodsb ; Read source 392 | get_variable_2: 393 | and rax, 0x1f ; 0x61-0x7a -> 0x01-0x1a 394 | shl rax, 3 ; rax <<= 3 395 | mov r8, vars 396 | add rax, r8; vars 397 | ; 398 | ; Avoid spaces 399 | ; 400 | spaces: 401 | cmp byte [rsi], ' ' ; Space found? 402 | jne spaces_3 ; No, return 403 | ; 404 | ; Avoid spaces after current character 405 | ; 406 | spaces_2: 407 | inc rsi ; Advance to next character 408 | jmp spaces 409 | spaces_3: 410 | ret 411 | 412 | ; 413 | ; Output unsigned number (uint_64) 414 | ; rax = value 415 | output_number: 416 | or rax, rax 417 | jns f26 418 | neg rax 419 | push rax 420 | mov al, '-' 421 | call syscall_putchar 422 | pop rax 423 | f26: 424 | mov rcx, 10 ; Divisor = 10 425 | cqo ; expand rax -> rdx:rax 426 | div rcx ; Divide rdx:rax / rcx = rax (... rdx) 427 | or rax, rax ; Nothing at left? 428 | push rdx 429 | je f8 ; No, jump 430 | call f26 ; Yes, output left side 431 | f8: pop rax 432 | add rax, '0' ; Output remainder as... 433 | jmp output ; ...ASCII digit 434 | 435 | ; 436 | ; Read number in input 437 | ; rax = result 438 | ; 439 | input_number: 440 | xor rbx, rbx ; BX = 0 441 | f11: xor rax, rax 442 | lodsb ; Read source 443 | sub al, '0' 444 | cmp al, 10 ; Digit valid? 445 | ; cbw ; al -> ax 446 | xchg rax, rbx 447 | jnc f12 ; No, jump 448 | mov rcx, 10 ; Multiply by 10 449 | mul rcx 450 | add rbx, rax ; Add new digit 451 | jmp f11 ; Continue 452 | 453 | f12: dec rsi ; SI points to first non-digit 454 | ret 455 | 456 | ; 457 | ; Handle 'system' statement 458 | ; 459 | system_statement: 460 | mov rdi, 0 461 | call syscall_exit 462 | 463 | ; 464 | ; Handle 'goto' statement 465 | ; 466 | goto_statement: 467 | call expr ; Handle expression 468 | ; and rax, 0xffff 469 | ;db 0xb9 ; MOV CX to jump over XOR AX,AX 470 | jmp f10 471 | 472 | ; 473 | ; Handle 'run' statement 474 | ; (equivalent to 'goto 0') 475 | ; 476 | run_statement: 477 | xor rax, rax 478 | f10: 479 | call find_line ; Find line in program 480 | f27: ;cmp word [running],0 ; Already running? 481 | cmp r10, 0 482 | je f31 483 | ; mov [running],ax ; Yes, target is new line 484 | mov r10, rax 485 | ret 486 | f31: 487 | push rax 488 | pop rsi 489 | add rax, max_length ; Point to next line 490 | mov r10, rax ; running = r10 491 | call statement ; Process current statement 492 | mov rax, r10 ; r10 = runnnig 493 | mov r9, program 494 | add r9, max_size 495 | cmp rax, r9 ; Reached the end? 496 | jne f31 ; No, continue 497 | ret ; Yes, return 498 | 499 | ; 500 | ; Find line in program 501 | ; Entry: 502 | ; rax = line number 503 | ; Result: 504 | ; rax = pointer to program 505 | ; rax = 0 if rax : out of range 506 | find_line: 507 | or rax, rax 508 | js find_line_err 509 | cmp rax, max_line 510 | jge find_line_err 511 | mov rcx, max_length 512 | mul rcx 513 | mov r9, program 514 | add rax, r9 515 | ret 516 | find_line_err: 517 | xor rax, rax 518 | ret 519 | 520 | ; 521 | ; Input line from keyboard 522 | ; Entry: 523 | ; al = prompt character 524 | ; Result: 525 | ; buffer 'line' contains line, finished with CR 526 | ; SI points to 'line'. 527 | ; 528 | input_line: 529 | call output 530 | mov rsi, line 531 | push rsi 532 | pop rdi ; Target for writing line 533 | f1: call input_key ; Read keyboard 534 | stosb ; Save key in buffer 535 | cmp al,0x08 ; Backspace? 536 | jne f2 ; No, jump 537 | dec rdi ; Get back one character 538 | dec rdi 539 | f2: cmp al, 0x0d ; CR pressed? 540 | jne f1 ; No, wait another key 541 | ret ; Yes, return 542 | 543 | ; 544 | ; Handle "print" statement 545 | ; 546 | print_statement: 547 | lodsb ; Read source 548 | cmp al, 0x0d ; End of line? 549 | je new_line ; Yes, generate new line and return 550 | cmp al, '"' ; Double quotes? 551 | jne f7 ; No, jump 552 | print_2: 553 | f9: 554 | lodsb ; Read string contents 555 | cmp al, '"' ; Double quotes? 556 | je f18 ; Yes, jump 557 | call output ; Output character 558 | jne f9 ; Jump if not finished with 0x0d (CR) 559 | ret ; Return 560 | 561 | f7: dec rsi 562 | call expr ; Handle expression 563 | call output_number ; Output result 564 | f18: lodsb ; Read next character 565 | cmp al, ';' ; Is it semicolon? 566 | jne new_line ; No, jump to generate new line 567 | ret ; Yes, return 568 | 569 | ; 570 | ; Read a key into al 571 | ; Also outputs it to screen 572 | ; 573 | input_key: 574 | ;mov ah,0x00 575 | ;int 0x16 576 | call syscall_getchar 577 | 578 | ; 579 | ; Screen output of character contained in al 580 | ; Expands 0x0d (CR) into 0x0a 0x0d (LF CR) 581 | ; 582 | output: 583 | cmp al, 0x0d 584 | jne f17 585 | ; 586 | ; Go to next line (generates LF+CR) 587 | ; 588 | new_line: 589 | mov al, 0x0a 590 | call f17 591 | mov al, 0x0d 592 | f17: 593 | ;mov ah,0x0e 594 | ;mov bx,0x0007 595 | call syscall_putchar ;int 0x10 596 | cmp al, 0x0d 597 | ret 598 | 599 | debug_n: 600 | push rax 601 | push rax 602 | call new_line 603 | mov al, '[' 604 | call syscall_putchar 605 | pop rax 606 | call output_number 607 | mov al, ']' 608 | call syscall_putchar 609 | call new_line 610 | pop rax 611 | ret 612 | 613 | ; 614 | ; List of statements of bootBASIC 615 | ; First one byte with length of string 616 | ; Then string with statement 617 | ; Then a word with the address of the code 618 | ; 619 | statements: 620 | db 3,"new" 621 | db 4,"list" 622 | db 3,"run" 623 | db 5,"print" 624 | db 5,"input" 625 | db 2,"if" 626 | db 4,"goto" 627 | db 6,"system" 628 | db 0 629 | statements_func: 630 | dq start 631 | dq list_statement 632 | dq run_statement 633 | dq print_statement 634 | dq input_statement 635 | dq if_statement 636 | dq goto_statement 637 | dq system_statement 638 | 639 | ; syscall for macOS 64bit 640 | 641 | section .bss 642 | putchar_buf resb 1 643 | getchar_buf resb 1 644 | 645 | section .text 646 | 647 | syscall_putchar: 648 | push rcx 649 | push rdx 650 | push rbx 651 | push rax 652 | push rdi 653 | push rsi 654 | 655 | mov rsi, putchar_buf ; buffer 656 | mov [rsi], al 657 | mov rax, 0x2000004 ; syscall 4: write 658 | mov rdi, 1 ; fd = stdout 659 | mov rdx, 1 ; size 660 | syscall 661 | 662 | pop rsi 663 | pop rdi 664 | pop rax 665 | pop rbx 666 | pop rdx 667 | pop rcx 668 | ret 669 | 670 | syscall_getchar: 671 | push rbx 672 | push rcx 673 | push rdx 674 | push rdi 675 | push rsi 676 | 677 | mov rax, 0x2000003 ; syscall 3: read 678 | mov rdi, 0 ; fd = stdin 679 | mov rsi, getchar_buf ; buffer 680 | mov rdx, 1 ; size 681 | syscall 682 | 683 | mov rsi, getchar_buf 684 | xor rax, rax 685 | mov al, [rsi] 686 | mov ah, 0 687 | 688 | pop rsi 689 | pop rdi 690 | pop rdx 691 | pop rcx 692 | pop rbx 693 | 694 | ; on Mac 0x0a -> 0x0d 695 | cmp al, 0x0a 696 | jne syscall_getchar_skip 697 | mov al, 0x0d 698 | syscall_getchar_skip: 699 | ret 700 | 701 | syscall_exit: ; retcode: rdi 702 | mov rax, 0x2000001 ; syscall 1: exit 703 | ;mov rdi, 0 ; retcode 704 | syscall 705 | ret 706 | -------------------------------------------------------------------------------- /basic.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taisukef/bootBASIC_64bit/5056fce5a3b0efdf64428fc8b2f57832b4fad120/basic.o -------------------------------------------------------------------------------- /bootBASIC_32bit/basic.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; bootBASIC interpreter in 512 bytes (boot sector) 3 | ; 4 | ; by Oscar Toledo G. 5 | ; http://nanochess.org/ 6 | ; 7 | ; (c) Copyright 2019 Oscar Toledo G. 8 | ; 9 | ; Creation date: Jul/19/2019. 10pm to 12am. 10 | ; Revision date: Jul/20/2019. 10am to 2pm. 11 | ; Added assignment statement. list now 12 | ; works. run/goto now works. Added 13 | ; system and new. 14 | ; Revision date: Jul/22/2019. Boot image now includes 'system' 15 | ; statement. 16 | ; 17 | 18 | ; Revision date: Jan/12/2020. Implimentation for macOS(386 32bit) by @taisukef 19 | 20 | ; 21 | ; USER'S MANUAL: 22 | ; 23 | ; Line entry is done with keyboard, finish the line with Enter. 24 | ; Only 19 characters per line as maximum. 25 | ; 26 | ; Backspace can be used, don't be fooled by the fact 27 | ; that screen isn't deleted (it's all right in the buffer). 28 | ; 29 | ; All statements must be in lowercase. 30 | ; 31 | ; Line numbers can be 1 to 999. 32 | ; 33 | ; 26 variables are available (a-z) 34 | ; 35 | ; Numbers (0-65535) can be entered and display as unsigned. 36 | ; 37 | ; To enter new program lines: 38 | ; 10 print "Hello, world!" 39 | ; 40 | ; To erase program lines: 41 | ; 10 42 | ; 43 | ; To test statements directly (interactive syntax): 44 | ; print "Hello, world!" 45 | ; 46 | ; To erase the current program: 47 | ; new 48 | ; 49 | ; To run the current program: 50 | ; run 51 | ; 52 | ; To list the current program: 53 | ; list 54 | ; 55 | ; To exit to command-line: 56 | ; system 57 | ; 58 | ; Statements: 59 | ; var=expr Assign expr value to var (a-z) 60 | ; 61 | ; print expr Print expression value, new line 62 | ; print expr; Print expression value, continue 63 | ; print "hello" Print string, new line 64 | ; print "hello"; Print string, continue 65 | ; 66 | ; input var Input value into variable (a-z) 67 | ; 68 | ; goto expr Goto to indicated line in program 69 | ; 70 | ; if expr1 goto expr2 71 | ; If expr1 is non-zero then go to line, 72 | ; else go to following line. 73 | ; 74 | ; Examples of if: 75 | ; 76 | ; if c-5 goto 20 If c isn't 5, go to line 20 77 | ; 78 | ; Expressions: 79 | ; 80 | ; The operators +, -, / and * are available with 81 | ; common precedence rules and signed operation. 82 | ; 83 | ; You can also use parentheses: 84 | ; 85 | ; 5+6*(10/2) 86 | ; 87 | ; Variables and numbers can be used in expressions. 88 | ; 89 | ; Sample program (counting 1 to 10): 90 | ; 91 | ; 10 a=1 92 | ; 20 print a 93 | ; 30 a=a+1 94 | ; 40 if a-11 goto 20 95 | ; 96 | ; Sample program (Pascal's triangle, each number is the sum 97 | ; of the two over it): 98 | ; 99 | ; 10 input n 100 | ; 20 i=1 101 | ; 30 c=1 102 | ; 40 j=0 103 | ; 50 t=n-i 104 | ; 60 if j-t goto 80 105 | ; 70 goto 110 106 | ; 80 print " "; 107 | ; 90 j=j+1 108 | ; 100 goto 50 109 | ; 110 k=1 110 | ; 120 if k-i-1 goto 140 111 | ; 130 goto 190 112 | ; 140 print c; 113 | ; 150 c=c*(i-k)/k 114 | ; 160 print " "; 115 | ; 170 k=k+1 116 | ; 180 goto 120 117 | ; 190 print 118 | ; 200 i=i+1 119 | ; 210 if i-n-1 goto 30 120 | ; 121 | 122 | ; cpu 8086 ; original 123 | cpu 386 ; for 32bit 124 | 125 | section .text 126 | global _main 127 | 128 | section .bss 129 | ram resb 0x10000 130 | putchar_buf resb 1 131 | getchar_buf resb 1 132 | 133 | section .text 134 | %ifndef com_file ; If not defined create a boot sector 135 | com_file: equ 0 136 | %endif 137 | 138 | %if com_file 139 | org 0x0100 140 | %else 141 | ;org 0x7c00 142 | %endif 143 | 144 | vars: equ ram + 0x7e00 ; Variables (multiple of 256) 145 | running: equ ram + 0x7e7e ; Running status 146 | line: equ ram + 0x7e80 ; Line input 147 | program: equ ram + 0x7f00 ; Program address 148 | ;stack: equ ram + 0xff00 ; Stack address 149 | max_line: equ 1000 ; First unavailable line number 150 | max_length: equ 20 ; Maximum length of line 151 | max_size: equ max_line * max_length ; Max. program size 152 | 153 | _main: 154 | start: 155 | %if com_file 156 | %else 157 | ;push cs ; For boot sector 158 | ;push cs ; it needs to setup 159 | ;push cs ; DS, ES and SS. 160 | ;pop ds 161 | ;pop es 162 | ;pop ss 163 | %endif 164 | 165 | cld ; Clear Direction flag 166 | mov edi,program ; Point to program 167 | mov al,0x0d ; Fill with CR 168 | mov cx,max_size ; Max. program size 169 | rep stosb ; Initialize 170 | ; 171 | ; Main loop 172 | ; 173 | main_loop: 174 | ;mov sp,stack ; Reinitialize stack pointer 175 | mov eax,main_loop 176 | push eax 177 | 178 | xor ax,ax ; Mark as interactive 179 | mov [running],ax 180 | mov al,'>' ; Show prompt 181 | call input_line ; Accept line 182 | call input_number ; Get number 183 | or ax,ax ; No number or zero? 184 | je statement ; Yes, jump 185 | call find_line ; Find the line 186 | xchg eax,edi 187 | ; mov cx,max_length ; CX loaded with this value in 'find_line' 188 | rep movsb ; Copy entered line into program 189 | ret 190 | 191 | ; 192 | ; Handle 'if' statement 193 | ; 194 | if_statement: 195 | call expr ; Process expression 196 | or ax,ax ; Is it zero? 197 | je f6 ; Yes, return (ignore if) 198 | statement: 199 | call spaces ; Avoid spaces 200 | cmp byte [esi],0x0d ; Empty line? 201 | je f6 ; Yes, return 202 | mov edi,statements ; Point to statements list 203 | f5: mov al,[edi] ; Read length of the string 204 | inc edi ; Avoid length byte 205 | and ax,0x00ff ; Is it zero? 206 | je f4 ; Yes, jump 207 | xchg ax,cx 208 | push esi ; Save current position 209 | f16: rep cmpsb ; Compare statement 210 | jne f3 ; Equal? No, jump 211 | pop eax 212 | call spaces ; Avoid spaces 213 | jmp word [edi] ; Jump to process statement 214 | 215 | f3: add edi,ecx ; Advance the list pointer 216 | inc edi ; Avoid the address 217 | inc edi 218 | pop esi 219 | jmp f5 ; Compare another statement 220 | 221 | f4: call get_variable ; Try variable 222 | push eax ; Save address 223 | lodsb ; Read a line letter 224 | cmp al,'=' ; Is it assignment '=' ? 225 | je assignment ; Yes, jump to assignment. 226 | 227 | ; 228 | ; An error happened 229 | ; 230 | error: 231 | mov esi,error_message 232 | call print_2 ; Show error message 233 | jmp main_loop ; Exit to main loop 234 | 235 | error_message: 236 | db "@#!",0x0d ; Guess the words :P 237 | 238 | ; 239 | ; Handle 'list' statement 240 | ; 241 | list_statement: 242 | xor eax,eax ; Start from line zero 243 | f29: push eax 244 | call find_line ; Find program line 245 | xchg eax,esi 246 | cmp byte [esi],0x0d ; Empty line? 247 | je f30 ; Yes, jump 248 | pop eax 249 | push eax 250 | call output_number ; Show line number 251 | f32: lodsb ; Show line contents 252 | call output 253 | jne f32 ; Jump if it wasn't 0x0d (CR) 254 | f30: pop eax 255 | inc eax ; Go to next line 256 | cmp eax,max_line ; Finished? 257 | jne f29 ; No, continue 258 | f6: 259 | ret 260 | 261 | ; 262 | ; Handle 'input' statement 263 | ; 264 | input_statement: 265 | call get_variable ; Get variable address 266 | push eax ; Save it 267 | mov al,'?' ; Prompt 268 | call input_line ; Wait for line 269 | ; 270 | ; Second part of the assignment statement 271 | ; 272 | assignment: 273 | call expr ; Process expression 274 | pop edi 275 | stosw ; Save onto variable 276 | ret 277 | 278 | ; 279 | ; Handle an expression. 280 | ; First tier: addition & subtraction. 281 | ; 282 | expr: 283 | call expr1 ; Call second tier 284 | f20: cmp byte [esi],'-' ; Subtraction operator? 285 | je f19 ; Yes, jump 286 | cmp byte [esi],'+' ; Addition operator? 287 | jne f6 ; No, return 288 | push ax 289 | call expr1_2 ; Call second tier 290 | f15: pop cx 291 | add ax,cx ; Addition 292 | jmp f20 ; Find more operators 293 | 294 | f19: 295 | push ax 296 | call expr1_2 ; Call second tier 297 | neg ax ; Negate it (a - b converted to a + -b) 298 | jmp f15 299 | 300 | ; 301 | ; Handle an expression. 302 | ; Second tier: division & multiplication. 303 | ; 304 | expr1_2: 305 | inc esi ; Avoid operator 306 | expr1: 307 | call expr2 ; Call third tier 308 | f21: cmp byte [esi],'/' ; Division operator? 309 | je f23 ; Yes, jump 310 | cmp byte [esi],'*' ; Multiplication operator? 311 | jne f6 ; No, return 312 | 313 | push ax 314 | call expr2_2 ; Call third tier 315 | pop cx 316 | imul cx ; Multiplication 317 | jmp f21 ; Find more operators 318 | 319 | f23: 320 | push ax 321 | call expr2_2 ; Call third tier 322 | pop cx 323 | xchg ax,cx 324 | cwd ; Expand AX to DX:AX 325 | idiv cx ; Signed division 326 | jmp f21 ; Find more operators 327 | 328 | ; 329 | ; Handle an expression. 330 | ; Third tier: parentheses, numbers and vars. 331 | ; 332 | expr2_2: 333 | inc esi ; Avoid operator 334 | expr2: 335 | call spaces ; Jump spaces 336 | lodsb ; Read character 337 | cmp al,'(' ; Open parenthesis? 338 | jne f24 339 | call expr ; Process inner expr. 340 | cmp byte [esi],')' ; Closing parenthesis? 341 | je spaces_2 ; Yes, avoid spaces 342 | jmp error ; No, jump to error 343 | 344 | f24: cmp al,0x40 ; Variable? 345 | jnc f25 ; Yes, jump 346 | dec esi ; Back one letter... 347 | call input_number ; ...to read number 348 | jmp spaces ; Avoid spaces 349 | 350 | f25: call get_variable_2 ; Get variable address 351 | xchg eax,ebx 352 | mov ax,[ebx] ; Read 353 | ret ; Return 354 | 355 | ; 356 | ; Get variable address 357 | ; 358 | get_variable: 359 | lodsb ; Read source 360 | get_variable_2: 361 | and ax,0x1f ; 0x61-0x7a -> 0x01-0x1a 362 | add ax,ax ; x 2 (each variable = word) 363 | add eax,vars 364 | ; 365 | ; Avoid spaces 366 | ; 367 | spaces: 368 | cmp byte [esi],' ' ; Space found? 369 | jne f22 ; No, return 370 | ; 371 | ; Avoid spaces after current character 372 | ; 373 | spaces_2: 374 | inc esi ; Advance to next character 375 | jmp spaces 376 | 377 | ; 378 | ; Output unsigned number 379 | ; AX = value 380 | ; 381 | output_number: 382 | f26: 383 | xor dx,dx ; DX:AX 384 | mov cx,10 ; Divisor = 10 385 | div cx ; Divide 386 | or ax,ax ; Nothing at left? 387 | push dx 388 | je f8 ; No, jump 389 | call f26 ; Yes, output left side 390 | f8: pop ax 391 | add al,'0' ; Output remainder as... 392 | jmp output ; ...ASCII digit 393 | 394 | ; 395 | ; Read number in input 396 | ; AX = result 397 | ; 398 | input_number: 399 | xor bx,bx ; BX = 0 400 | f11: lodsb ; Read source 401 | sub al,'0' 402 | cmp al,10 ; Digit valid? 403 | cbw 404 | xchg ax,bx 405 | jnc f12 ; No, jump 406 | mov cx,10 ; Multiply by 10 407 | mul cx 408 | add bx,ax ; Add new digit 409 | jmp f11 ; Continue 410 | 411 | f12: dec esi ; SI points to first non-digit 412 | f22: 413 | ret 414 | 415 | ; 416 | ; Handle 'system' statement 417 | ; 418 | system_statement: 419 | ;int 0x20 420 | call syscall_exit 421 | 422 | ; 423 | ; Handle 'goto' statement 424 | ; 425 | goto_statement: 426 | call expr ; Handle expression 427 | ;db 0xb9 ; MOV CX to jump over XOR AX,AX 428 | jmp f10 429 | 430 | ; 431 | ; Handle 'run' statement 432 | ; (equivalent to 'goto 0') 433 | ; 434 | run_statement: 435 | xor ax,ax 436 | f10: 437 | call find_line ; Find line in program 438 | f27: cmp word [running],0 ; Already running? 439 | je f31 440 | mov [running],ax ; Yes, target is new line 441 | ret 442 | f31: 443 | push eax 444 | pop esi 445 | add ax,max_length ; Point to next line 446 | mov [running],ax ; Save for next time 447 | call statement ; Process current statement 448 | mov ax,[running] 449 | cmp ax,program + max_size ; Reached the end? 450 | jne f31 ; No, continue 451 | ret ; Yes, return 452 | 453 | ; 454 | ; Find line in program 455 | ; Entry: 456 | ; ax = line number 457 | ; Result: 458 | ; eax = pointer to program 459 | find_line: 460 | mov ecx,max_length 461 | mul ecx 462 | add eax,program 463 | ret 464 | 465 | ; 466 | ; Input line from keyboard 467 | ; Entry: 468 | ; al = prompt character 469 | ; Result: 470 | ; buffer 'line' contains line, finished with CR 471 | ; SI points to 'line'. 472 | ; 473 | input_line: 474 | call output 475 | mov esi,line 476 | push esi 477 | pop edi ; Target for writing line 478 | f1: call input_key ; Read keyboard 479 | stosb ; Save key in buffer 480 | cmp al,0x08 ; Backspace? 481 | jne f2 ; No, jump 482 | dec edi ; Get back one character 483 | dec edi 484 | f2: cmp al, 0x0d ; CR pressed? 485 | jne f1 ; No, wait another key 486 | ret ; Yes, return 487 | 488 | ; 489 | ; Handle "print" statement 490 | ; 491 | print_statement: 492 | lodsb ; Read source 493 | cmp al,0x0d ; End of line? 494 | je new_line ; Yes, generate new line and return 495 | cmp al,'"' ; Double quotes? 496 | jne f7 ; No, jump 497 | print_2: 498 | f9: 499 | lodsb ; Read string contents 500 | cmp al,'"' ; Double quotes? 501 | je f18 ; Yes, jump 502 | call output ; Output character 503 | jne f9 ; Jump if not finished with 0x0d (CR) 504 | ret ; Return 505 | 506 | f7: dec esi 507 | call expr ; Handle expression 508 | call output_number ; Output result 509 | f18: lodsb ; Read next character 510 | cmp al,';' ; Is it semicolon? 511 | jne new_line ; No, jump to generate new line 512 | ret ; Yes, return 513 | 514 | ; 515 | ; Read a key into al 516 | ; Also outputs it to screen 517 | ; 518 | input_key: 519 | ;mov ah,0x00 520 | ;int 0x16 521 | call syscall_getchar 522 | 523 | ; 524 | ; Screen output of character contained in al 525 | ; Expands 0x0d (CR) into 0x0a 0x0d (LF CR) 526 | ; 527 | output: 528 | cmp al,0x0d 529 | jne f17 530 | ; 531 | ; Go to next line (generates LF+CR) 532 | ; 533 | new_line: 534 | mov al,0x0a 535 | call f17 536 | mov al,0x0d 537 | f17: 538 | ;mov ah,0x0e 539 | ;mov bx,0x0007 540 | call syscall_putchar ;int 0x10 541 | cmp al,0x0d 542 | ret 543 | 544 | ; 545 | ; List of statements of bootBASIC 546 | ; First one byte with length of string 547 | ; Then string with statement 548 | ; Then a word with the address of the code 549 | ; 550 | statements: 551 | db 3,"new" 552 | dw start 553 | 554 | db 4,"list" 555 | dw list_statement 556 | 557 | db 3,"run" 558 | dw run_statement 559 | 560 | db 5,"print" 561 | dw print_statement 562 | 563 | db 5,"input" 564 | dw input_statement 565 | 566 | db 2,"if" 567 | dw if_statement 568 | 569 | db 4,"goto" 570 | dw goto_statement 571 | 572 | db 6,"system" 573 | dw system_statement 574 | 575 | db 0 576 | 577 | ; 578 | ; Boot sector filler 579 | ; 580 | %if com_file 581 | %else 582 | ;times 510-($-$$) db 0x4f 583 | ;db 0x55,0xaa ; Make it a bootable sector 584 | %endif 585 | 586 | syscall_param3: 587 | push dword ebp 588 | mov ebp, esp 589 | push dword edx 590 | push dword ecx 591 | push dword ebx 592 | sub esp, 4 593 | int 0x80 594 | add esp, 16 595 | pop ebp 596 | ret 597 | 598 | syscall_putchar: 599 | push ecx 600 | push edx 601 | push ebx 602 | push eax 603 | mov [putchar_buf], al 604 | mov ecx, putchar_buf 605 | mov edx, 1 ; size 606 | mov ebx, 1 ; stdout 607 | mov eax, 4 ; syscall SYS_write 608 | call syscall_param3 609 | pop eax 610 | pop ebx 611 | pop edx 612 | pop ecx 613 | ret 614 | 615 | syscall_getchar: 616 | push ebx 617 | push ecx 618 | push edx 619 | mov ecx, getchar_buf 620 | mov edx, 1 ; size 621 | mov ebx, 0 ; stdin 622 | mov eax, 3 ; syscall SYS_read 623 | call syscall_param3 624 | mov al, [getchar_buf] 625 | mov ah, 0 626 | pop edx 627 | pop ecx 628 | pop ebx 629 | 630 | ; on Mac 0x0a -> 0x0d 631 | cmp al, 0x0a 632 | jne syscall_getchar_skip 633 | mov al, 0x0d 634 | syscall_getchar_skip: 635 | ret 636 | 637 | syscall_exit: 638 | mov ecx, 0 639 | mov edx, 0 640 | mov ebx, 0 ; exit code 641 | mov eax, 1 ; syscall SYS_exit 642 | call syscall_param3 643 | ret 644 | -------------------------------------------------------------------------------- /bootBASIC_32bit/basic.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taisukef/bootBASIC_64bit/5056fce5a3b0efdf64428fc8b2f57832b4fad120/bootBASIC_32bit/basic.o -------------------------------------------------------------------------------- /bootBASIC_32bit/bootbasic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taisukef/bootBASIC_64bit/5056fce5a3b0efdf64428fc8b2f57832b4fad120/bootBASIC_32bit/bootbasic -------------------------------------------------------------------------------- /bootBASIC_32bit/c.sh: -------------------------------------------------------------------------------- 1 | nasm -f macho32 basic.asm 2 | ld -lSystem basic.o -o bootbasic 3 | ./bootbasic 4 | -------------------------------------------------------------------------------- /bootbasic: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taisukef/bootBASIC_64bit/5056fce5a3b0efdf64428fc8b2f57832b4fad120/bootbasic -------------------------------------------------------------------------------- /c.sh: -------------------------------------------------------------------------------- 1 | nasm -f macho64 basic.asm 2 | ld -lSystem basic.o -o bootbasic 3 | ./bootbasic 4 | echo $? 5 | --------------------------------------------------------------------------------