[Index] [Previous] [Next]

3.2 Initialisation Part 2

The results of IO diagnostics are in various registers. In this first block we configure the IO code with these results.

Configure InputChar's device-ready bit and conditional jump.
0D8E 62 ConfigIOcode MOV H,D
0D8F 68 MOV L,B
0D90 228503 SHLD InputChar+3
Configure TestBreakKey's device-ready bit.
0D93 7C MOV A,H
0D94 E6C8 ANI C8
0D96 67 MOV H,A
0D97 227604 SHLD 0476
0D9A EB XCHG
0D9B 227A03 SHLD 037A
0D9E 3A8C0D LDA 0D8C
0DA1 328303 STA 0383
0DA4 327404 STA 0474
0DA7 3C INR A
0DA8 328A03 STA 038A
0DAB 81 ADD C
0DAC 327803 STA 0378
0DAF 3C INR A
0DB0 328003 STA 0380

 

"Memory Size?"

In this block we ask the user how much memory they have, in bytes.

Set CURRENT_LINE to -1 to indicate direct mode.
0DB3 21FFFF LXI H,FFFF
0DB6 226101 SHLD CURRENT_LINE
Print a new line, followed by the "MEMORY SIZE?" prompt.
0DB9 CD8A05 CALL NewLine
0DBC 21F00E LXI H,szMemorySize
0DBF CDA305 CALL PrintString
0DC2 CDC202 CALL InputLineWith'?'
0DC5 D7 RST NextChar
0DC6 B7 ORA A
0DC7 C2DE0D JNZ 0DDE
No answer given to the request for memory size, therefore we find the top of memory ourselves. This is done by writing alternating 0x37 and 0x36's to progressively higher addresses and reading the values back from memory. When the value read is not the value written, we know we have written past the top of memory.
0DCA 21FC0E LXI H,UnusedMemory
0DCD 23 FindMemTopLoop INX H
0DCE 3E37 MVI A,37
0DD0 77 MOV M,A
0DD1 BE CMP M
0DD2 C2EA0D JNZ DoneMemSize
0DD5 3D DCR A
0DD6 77 MOV M,A
0DD7 BE CMP M
0DD8 CACD0D JZ FindMemTopLoop
0DDB C3EA0D JMP DoneMemSize
Memory size has been given in bytes. Here we convert the string input to an integer value and error out if it's 0 or a non-numeric input.
0DDE 211301 LXI H,LINE_BUFFER
0DE1 CD9D04 CALL LineNumberFromStr
0DE4 B7 ORA A
0DE5 C2D001 JNZ SyntaxError
0DE8 EB XCHG
0DE9 2B DCX H
Put the address of the last word of RAM on the stack.
0DEA 2B DoneMemSize DCX H
0DEB E5 PUSH H

 

"Terminal Width?"

Ask the user how many columns wide their terminal is. This defaults to 72 if empty input is given.

Print the "TERMINAL WIDTH" prompt and get user input.
0DEC 21B40E GetTerminalWidth LXI H,szTerminalWidth
0DEF CDA305 CALL PrintString
0DF2 CDC202 CALL InputLineWith'?'
If no input given then we'll use the hard-coded default (72) and can jump straight to the next section.
0DF5 D7 RST NextChar
0DF6 B7 ORA A
0DF7 CA1B0E JZ DoOptionalFns
User has given an input for terminal wdith, so convert that to an integer in DE.
0DFA 211301 LXI H,LINE_BUFFER
0DFD CD9D04 CALL LineNumberFromStr
If user-supplied terminal width is >=256 or <16 then that's out of range so jump back to ask again.
0E00 7A MOV A,D
0E01 B7 ORA A
0E02 C2EC0D JNZ GetTerminalWidth
0E05 7B MOV A,E
0E06 FE10 CPI 10
0E08 DAEC0D JC GetTerminalWidth
Config printing code with the user-supplied terminal width.
0E0B 326F03 STA OutChar_tail+1

Calculate the column of the last tab-break and write this number to the right place in the ToNextTabBreak function. The tab-break size is 14, so the last tab-break is calculated as (width - ((width % 14)+14). So for 72, the last tab brk is at column 56.

0E0E D60E CalcTabBrkSize SUI 0E
0E10 D20E0E JNC CalcTabBrkSize
0E13 C61C ADI 1C
0E15 2F CMA
0E16 3C INR A
0E17 83 ADD E
0E18 32B705 STA ToNextTabBreak+4

 

"Sin? Rnd? Sqr?"

Now we ask the user whether which optional inline functions they want support for. If they answer Y(es) to any, they do not get an option to turn off support for the later ones, ie if you say yes to SIN you have implicitly accepted RND and SQR too. If functions are turned off, the memory they occupy is reclaimed for program space (look for where PROGRAM_BASE gets set and how it is calculated).

Initialise HL to point to the first optional function descriptor (which is for SIN).
0E1B 21850E DoOptionalFns LXI H,OPT_FN_DESCS
Push the first word of the descriptor onto the stack. This is where program storage can begin should the function be accepted.
0E1E F7 OptionalFnsLoop RST PushNextWord
Have we gone past the end of the descriptor table? If so, jump down a bit and on to InitProgramBase.
0E1F 11990E LXI D,szWantSin
0E22 E7 RST CompareHLDE
0E23 CA320E JZ 0E32
Get the address of the string prompt into HL, print the prompt, get the input, get the first character of that input into A and restore HL.
0E26 F7 RST PushNextWord
0E27 E3 XTHL
0E28 CDA305 CALL PrintString
0E2B CDC202 CALL InputLineWith'?'
0E2E D7 RST NextChar
0E2F E1 POP H
If 'Y'es selected, ie keep this function, then pop the beginning of program storage into DE and jump down to InitProgramBase
0E30 FE59 CPI 'Y'
0E32 D1 POP D
0E33 CA470E JZ InitProgramBase
If user has entered something other than 'N'o then jump back to the start of the optional functions section.
0E36 FE4E CPI 'N'
0E38 C21B0E JNZ DoOptionalFns
User has selected No. Here we get the next word of the descriptor into HL, which is the optional function's entry in the KW_INLINE_FNS table.
0E3B F7 RST PushNextWord
0E3C E3 XTHL
Write the address of FunctionCallError into the functions' entry in KW_INLINE_FNS.
0E3D 119804 LXI D,FunctionCallError
0E40 73 MOV M,E
0E41 23 INX H
0E42 72 MOV M,D
Restore HL and jump back to deal with the next optional function.
0E43 E1 POP H
0E44 C31E0E JMP OptionalFnsLoop
Got the bottom of program memory in DE. Here we write a null byte to that address and store the address in PROGRAM_BASE.
0E47 EB InitProgramBase XCHG
0E48 3600 MVI M,00
0E4A 23 INX H
0E4B 226501 SHLD PROGRAM_BASE
Get the address of the last byte of RAM into HL and push PROGRAM_BASE on the stack.
0E4E E3 XTHL
If the address of the last byte of RAM is less than 0x0F1A then Out of Memory (OM) error.
0E4F 111A0F LXI D,0F1A
0E52 E7 RST CompareHLDE
0E53 DACD01 JC ErrorOutOfMem
Get PROGRAM_BASE into DE and set the stack pointer and STACK_TOP to the very top of memory.
0E56 D1 POP D
0E57 F9 SPHL
0E58 226301 SHLD STACK_TOP
Get PROGRAM_BASE into HL and STACK_TOP into DE and check that PROGRAM_BASE is far enough from the stack pointer (32 bytes away).
0E5B EB XCHG
0E5C CDC301 CALL CheckEnoughMem
Bytes Free (in HL) is calculated here as (STACK_TOP - PROGRAM_BASE) - 16.
0E5F 7B MOV A,E
0E60 95 SUB L
0E61 6F MOV L,A
0E62 7A MOV A,D
0E63 9C SBB H
0E64 67 MOV H,A
0E65 01F0FF LXI B,FFF0
0E68 09 DAD B
Print version information - a new line, followed by the number of Bytes Free, followed by the version info string.
0E69 CD8A05 CALL NewLine
0E6C CD370B CALL PrintNumber
0E6F 21C30E LXI H,szVersionInfo
0E72 CDA305 CALL PrintString
Change code at start of Main to call PrintString instead of restarting.
0E75 21A305 LXI H,PrintString
0E78 22FD01 SHLD Main+4
Call NEW handler to initalise BASIC interpreter variables, setup a blank program, etc.
0E7B CD9602 CALL New+1
Set the JMP address at the start of BASIC to jump to Main instead of Init.
0E7E 21F901 LXI H,Main
0E81 220200 SHLD Start+2
Jump to Main
0E84 E9 PCHL

 

Optional Function Descriptors

blah

Optional function descriptors. The first one is for the SIN function.
0E85 170D OPT_FN_DESCS DW 0D17
  990E   DW szWantSin
  4900   DW KW_INLINE_FNS+12
RND function.
0E8B 950C   DW 0C95
  A20E   DW szWantRnd
  4700   DW KW_INLINE_FNS+10
SQR function.
0E91 5F0C   DW 0C5F
  AB0E   DW szWantSqr
  4500   DW KW_INLINE_FNS+8
Finally, the lowest address for program space if all optional functions are switched off
0E97 210C   DW 0C21

 

Init Strings

String prompts for the optional inline functions.
0E99 57414E54205349CE00 szWantSin DS "WANT SIN\0"
0EA2 57414E5420524EC400 szWantRnd DS "WANT RND\0"
0EAB 57414E54205351D200 szWantSqr DS "WANT SQR\0"
Other string constants
0EB4 5445524D494E414C2057494454C800 szTerminalWidth DS "TERMINAL WIDTH\0"
0EC3

20425954455320465245C50D0D
42415349432056455253494F4E20332E
B20D5B344B2056455253494F4EDD0D00

szVersionInfo DS " BYTES FREE\r\r"
"BASIC VERSION 3."
"2\r[4K VERSION]\r\0"
0EF0 4D454D4F52592053495AC500 szMemorySize DS "MEMORY SIZE\0"

EFC to FFF are unused.

 


[Index] [Previous] [Next]