HiSoft Pascal Primer cover: a square, a triangle and a circle drawn and filled by a HiSoft Pascal program on the Tatung Einstein
← Back to Courses
module
19

Reaching The Machine

Introduction

The Turbo course's S26 reached into the machine with Mem[] and Port[], and S39 put machine code into a program with inline. HiSoft Pascal can do all of it, with procedures and functions of its own instead of Turbo's arrays - and one of them knows about types, which Turbo's did not.

Memory

ADDR(V) gives the address of a variable, as Turbo's Addr did.

PEEK(A,T) reads memory at address A - and the second thing you give it is a type: PEEK(A,CHAR) reads one byte as a character, PEEK(A,INTEGER) two bytes as an integer, and so on for any type. Turbo's Mem[A] only ever gave a byte. ORD(PEEK(A,CHAR)) is the byte as a number.

POKE(A,V) writes the value V at A, taking as many bytes as V's type needs.

An integer is kept low byte first: 1234 is 210 and then 4 (4 × 256 + 210). Hexadecimal constants (#1C00) are handy for addresses (S6).

Ports

OUT(P,C) sends a byte to the I/O port P - and the byte is given as a CHAR, so a number goes in with CHR: OUT(9,CHR(#1C)). INP(P) reads a port, and gives a CHAR back.

The Einstein's screen chip listens on ports 8 and 9, as the Turbo course used them to give a character a new shape: the font starts at #1800, eight bytes to a character, six dots wide. Do it under (*$C-*). With the CTRL-C check on, the check between one OUT and the next disturbs the screen chip, and the new shape never arrives - the character just prints blank.

The DOS

CPM(F,D) calls the disc operating system's function number F, giving it D, and returns what it answers. CPM(25,0) is the logged drive (0 is drive 0); CPM(2,65) prints A, the character with code 65.

Machine Code

USER(A) calls machine code at address A. The code must end with a RET.

INLINE(...) puts bytes straight into the compiled program, where the Z80 runs them. Only constants: Turbo's inline could name a variable and get its address; here that is error 14. HiSoft's own manual shows it doubling a real number in a single instruction - the bytes #DD,#34,3 add one to the number's exponent:

FUNCTION MULTBY2(X:REAL):REAL;
BEGIN
INLINE(#DD,#34,3);
MULTBY2:=X
END;

MULTBY2(3.5) is 7.00. It is the bridge to the Z80 assembly course: the bytes are machine code, and that course is where you learn to write them.

The Code

A new shape for character 128, and a look at how a number is stored:

10 (*$C-*)
20 PROGRAM FACE;
30 VAR I,N:INTEGER;
40 S:ARRAY[1..8] OF INTEGER;
50 BEGIN
60 S[1]:=#78; S[2]:=#84; S[3]:=#CC; S[4]:=#84;
70 S[5]:=#B4; S[6]:=#84; S[7]:=#78; S[8]:=#00;
80 OUT(9,CHR(#00));
90 OUT(9,CHR(#1C+#40));
100 FOR I:=1 TO 8 DO OUT(8,CHR(S[I]));
110 WRITELN('HELLO ',CHR(128),CHR(128),CHR(128));
120 N:=1234;
130 WRITELN(N,'IS ',ORD(PEEK(ADDR(N),CHAR)),
140 'AND ',ORD(PEEK(ADDR(N)+1,CHAR)));
150 WRITELN('DRIVE ',CPM(25,0))
160 END.

Lines 60 and 70 are the face, a row of dots to each number. Lines 80 and 90 point the screen chip at character 128's shape - #1800 + 128 × 8 is #1C00, sent low byte first, with #40 added to the high byte to say "about to write". Line 100 writes the eight rows.

Starting from

FACE.ASC saved from XBAS; HPEIN FACE.

What you should see

HELLO ☺☺☺
1234 IS 210 AND 4
DRIVE 0
  • with three small faces after HELLO.

Change One Thing

  • Take out line 10. What do the three characters look like now?
  • Change #CC in line 60 to #FC. What happens to the face's eyes?
  • Change line 130's CHAR to INTEGER, and take out the ORD( ) round it. What does it print?

Exercises

19.1 Give character 129 the shape of a small arrow, and print a row of them.

19.2 Print the four bytes PEEK finds at the address of a REAL holding 1.0.

Worked solutions are in Appendix II.

When It Goes Wrong

SymptomCause
A redefined character prints blankThe CTRL-C check spoiled the writes. (*$C-*) at the top.
*ERROR* at OUT(9,#1C)OUT takes a CHAR: CHR(#1C).
*ERROR* 14 in an INLINEOnly constants go in an INLINE.

Summary

ADDR gives an address; PEEK(A,T) reads any type there and POKE writes; OUT and INP work the ports with CHARs; CPM calls the DOS. USER calls machine code, and INLINE puts constant bytes into the program. Work the screen chip under (*$C-*).

Next

S20, Where You Go From Here.

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.