Page 1 of 2

New to Machine code, help required

Posted: Thu Dec 06, 2018 5:26 pm
by Panther
Hi peeps,

New to the forum and looking for guidance as I take my first steps into ZX81 machine code !!
I’ve been reading through ‘Mastering Machine Code on your ZX81’ and I’m understanding it so far but I’m a little confused with one of the most basic things;

Printing to the screen !!

One of the examples is;
3E97 LD A,inverse-*
CD0808 CALL PRINT
18F9 JR START

Which from what I understand loads the code for an inverse asterix into register A, call a print routine to print the contents of A in the next available print position and finally jumps back 7 bytes to repeat until the screen is full and you get an error 5 out of screen error.

Now I’ve tried a couple of things to fill the screen without the error and I’m failing miserably but I can’t see where I am going wrong, I know it’s probably really simple but any pointers would help.

So far I’ve tried;

3E08 LD A, Character 8
01D602 LD BC, 726
CD0808 CALL PRINT
0B DEC BC
20FA JR NZ, CALL PRINT
C9 RET

And

01D602 LD BC,726
3E08 LD A, Inverse space
CD0808 CALL PRINT
EBD0 LDIR
C9 RET

The first fills the screen with an out of screen error, the second just prints one character and stops.

I thought the JR NZ would jump back until the last calculation was zero (BC), likewise I thought the LDIR would repeat again until BC has decremented to zero

Plenty more questions to come I think !

Re: New to Machine code, help required

Posted: Thu Dec 06, 2018 7:38 pm
by rune
Hi Panther, where does the 726 value come from? The standard screen is 22 lines x 32 columns so 704 positions.

Also, if you press the CONT key, your first routine will print another screen of characters... Thats because the JR NZ tests the value of the A Register, you are decrementing BC.

So, the routine prints the character for ever with breaks when the screen is filled.

The second example you print the first value thats held in A

But LDIR uses the HE and DE registers - Specifically the contents of memory address pointed to by HL is loaded into the memory address pointed to by DE, BC is decremented - HL and DE incremented and the cycle repeated until BC = 0.
A is ignored.

Here is my take on the first example. The code will stop with 0/10 which means the program has completed. Formatting is lost, so I have used "."s to get the code indented.

............. LD BC, 704
PRNT....... LD A, 44
............. CALL PRINT
............. DEC BC
............. LD A, B
............. OR C
............. JR NZ, PRNT
............. RET

Re: New to Machine code, help required

Posted: Thu Dec 06, 2018 8:11 pm
by XavSnap
Use the RST10 function, to avoid to destroyed the n/l character...

Code: Select all

Lb40A4:
	LD HL,$03BF 
Lb40A7:
	LD A,151 ; '*'
	RST 10H ; Display= A reg.
	LD A,$00 
	DEC HL 
	CP H 
	JR NZ, Lb40A7 ; [$40A7:16551]
	RET ; ==========================
@rune : (22 lines x 32 )+23 (new/line=$76)

Re: New to Machine code, help required

Posted: Thu Dec 06, 2018 8:45 pm
by rune
@XavSnap, yes, but to be pedantic, 704 + 23 N/L is 727, not 726. Also using Call Print or RST#10 would only print in printable locations, so the count has to be 704.

Why did you use $03BF as the counter? Isnt that more than a standard screen?

Re: New to Machine code, help required

Posted: Thu Dec 06, 2018 11:16 pm
by siggi
rune wrote: Thu Dec 06, 2018 7:38 pm Also, if you press the CONT key, your first routine will print another screen of characters... Thats because the JR NZ tests the value of the A Register, you are decrementing BC.
No, JR NZ tests the Z-flag, which is part of the F register. It could be set by a lot of instructions (like "DEC C" or "AND A"), but not by 16 bit operations like "DEC BC".

Siggi

Re: New to Machine code, help required

Posted: Fri Dec 07, 2018 1:06 am
by Panther
rune wrote: Thu Dec 06, 2018 7:38 pm Hi Panther, where does the 726 value come from? The standard screen is 22 lines x 32 columns so 704 positions.

Also, if you press the CONT key, your first routine will print another screen of characters... Thats because the JR NZ tests the value of the A Register, you are decrementing BC.

So, the routine prints the character for ever with breaks when the screen is filled.

The second example you print the first value thats held in A

But LDIR uses the HE and DE registers - Specifically the contents of memory address pointed to by HL is loaded into the memory address pointed to by DE, BC is decremented - HL and DE incremented and the cycle repeated until BC = 0.
A is ignored.

Here is my take on the first example. The code will stop with 0/10 which means the program has completed. Formatting is lost, so I have used "."s to get the code indented.

............. LD BC, 704
PRNT....... LD A, 44
............. CALL PRINT
............. DEC BC
............. LD A, B
............. OR C
............. JR NZ, PRNT
............. RET
Hi rune,

The 726 comes from 32 + the new line = 33 x 22 = 726 (only what I've read in the book)

So from this "But LDIR uses the HE and DE registers - Specifically the contents of memory address pointed to by HL is loaded into the memory address pointed to by DE, BC is decremented - HL and DE incremented and the cycle repeated until BC = 0.
A is ignored.
"

Are you saying it's printing the contents of A (first character) and then continuing until BC=0 but just printing blank spaces (ignoring A) ?

Re: New to Machine code, help required

Posted: Fri Dec 07, 2018 2:07 am
by XavSnap
5 examples to fill a screen.

Code: Select all

#include ZX81.sym

#define ORG  .org       ; TASM cross-assembler definitions
#define equ  .equ
;-----------------------------------

;------- Rom and Ram Symbols -------
RAM_D_FILE equ $400C ; D_file address.
EXTERR equ $005B ; Basic Break function ! Ignore line instructions.
CURSEUR equ $8F5 ; Point to PRINT AT DEST.(BC=X,Y)
CHAINE equ $B6B ; PRINT A CHAINE (BC=LEN;DE=TEXT LOC)
	
ORG 16514
;--------------------------------1
	LD BC,0000
	CALL CURSEUR
	LD BC,22*32
LOOP1:
	LD A,157 ; '1'
	RST 10H
	DEC BC
	LD A,B
	OR C
	JR NZ,LOOP1
	RET
;--------------------------------2

	LD HL,(RAM_D_FILE)
	LD B,158 ; '2'
	LD DE,32*24+23
LOOP2:
	LD A,$76
	INC HL
	CP (HL)
	DEC DE
	JR Z,LOOP2
	LD (HL),B
	LD A,D
	OR E
	RET Z
	JR LOOP2

;--------------------------------3

	LD HL,(RAM_D_FILE)
LOOP3:
	INC HL
	LD D,H
	LD E,L
	INC DE
	LD A,159 ; '3'
	LD (HL),A
	LD BC,31
	LDIR
	LD A,$80
	EX DE,HL
	INC HL
	CP (HL)
	EX DE,HL
	RET Z
	INC HL
	JR LOOP3

;--------------------------------4

	LD HL,(RAM_D_FILE)
	INC HL
	LD D,H
	LD E,L
	INC DE
	LD A,160 ; '4'
	LD (HL),A
	LD BC,31
	LDIR
	LD BC,$0100
	CALL CURSEUR
	LD L,21

LOOP4:

	LD DE,(RAM_D_FILE)
	INC DE
	LD BC,32
	CALL CHAINE
	DEC L
	RET Z
	RET Z
	JR LOOP4

;--------------------------------5

Lb40A4:
	LD BC,0000
	CALL CURSEUR
		LD HL,$03BF 
Lb40A7:
		LD A,161 ; '5'
		RST 10H ; Display= A reg.
		LD A,$00 
		DEC HL 
		CP H 
		JR NZ, Lb40A7 ; [$40A7:16551]
		RET ; ==========================
	
.end
fill_test.zip
(54.07 KiB) Downloaded 203 times

Re: New to Machine code, help required

Posted: Fri Dec 07, 2018 2:47 am
by 1024MAK
@Panther

A few things to keep in mind.

Some of the Z80 instructions are designed to be compatible with the Intel 8080. Hence the slightly different way that 8 bit and 16 bit operations are handled with respect to the effect on the flag (F) register. The conditional jumps are based on the relevant bit in the flag register. Check each op-code to see if and what affect it has (if any) on the flags.

Some calls to the ROM code will affect some registers, as the routine may use some of the registers for it’s own purposes.

Mark

Re: New to Machine code, help required

Posted: Fri Dec 07, 2018 3:06 am
by XavSnap
:mrgreen:

Yes,

Code: Select all

	INC DE
	LD BC,32
	CALL CHAINE
	DEC L
	RET Z
	RET Z
	JR LOOP4
The first RET Z don't work.
I tryed using the A register with a "OR A" to clean the F register, CCF for the carry...
But, the ROM seem to add a new jump to the PC accumulator...
Two RET seem working !
:lol:

Re: New to Machine code, help required

Posted: Fri Dec 07, 2018 9:28 am
by rune
Hi Xavsnap
Are you saying it's printing the contents of A (first character) and then continuing until BC=0 but just printing blank spaces (ignoring A) ?
Yes, the LDIR command only operates on HL, DE, BC registers. We dont know what addresses HL or BC are pointing to, just that they pass the contents from HL to DE and increase as BC decreases. (Probably) nothing is being printed to the screen, not even blank characters during the LDIR