New to machine code...seeking assistance.

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

New to machine code...seeking assistance.

Post by MonkZy »

I am taking some very early steps into assembly. I have a task I would like to perform with machine code :

'Paint' a 22x18 character square with attributes stored in memory. It will behave like a double buffer routine but just for colour attributes. I wish to manipulate the attributes stored in memory using BASIC and then run my routine to rapidly update the attributes in display memory. Simples!

I had a machine code routine from ZX Computing for copying the entire graphics memory to and from memory. I used this routine in many BASIC programs back in the 80's to mask the terrible slow DRAW routines used in BASIC. I have shown the decimal codes because I will be using a READ a : POKE x,a in a FOR-NEXT loop to load the routine into memory.

Code: Select all

Decimal		Mnemonics
17,x,x		LD DE,26000	;load de with address to copy from (24000)
33,0,64		LD HL,16384	;load hl with address to copy to (16384)
6,27		LD B,27
197		PUSH BC
6,0		LD B,256
26		LD A,(DE)
119		LD (HL),A
19		INC DE
35		INC HL
16,249		DJNZ,-6
193		POP BC
16,244		DJNZ,-11
201		RET
This code works great, and fast too. I do not need pixel data and only require a window so I modified the code :

Code: Select all

Decimal		Mnemonics
17,24,246	LD DE,63000	;load de with address to copy from (63000)
33,0,64		LD HL,22629	;load hl with address to copy to (22629)
6,10		LD B,10		;loop 600 times
197		PUSH BC
6,60		LD B,60
26		LD A,(DE)
119		LD (HL),A
19		INC DE
35		INC HL
16,249		DJNZ,-6
193		POP BC
16,244		DJNZ,-11
201		RET
This works great. However, the routine is changing attributes outside of my 22x19 char window. Not the end of the world because it is quick anyway but I wanted a neater output. This is my theoretical code :

Code: Select all

Decimal		Mnemonics
17,24,246	LD DE,63000	;load de with address to copy from (63000)
33,x,x		LD HL,22629	;load hl with address to copy to (22629)
6,10		LD B,18		
197		PUSH BC
6,60		LD B,22
26		LD A,(DE)
119		LD (HL),A
19		INC DE
35		INC HL
16,249		DJNZ,-6
1,10,0		LD BC,10
9,		ADD HL,BC
193		POP BC
16,240		DJNZ,-15
201		RET
Here is my BASIC implementation of the code :

Code: Select all

  15 CLEAR 63999

  20 REM LOAD *"m";1;"screen"SCREEN$

  30 LET c=63000:LET d=0
  40 FOR a=3 TO 20
  50 FOR b=5 TO 26
  60 PRINT AT a,b; PAPER d*2;" "
  70 POKE c,d*16
  80 LET d=NOT(d):LET c=c+1
  90 NEXT b
  95 LET d=NOT(d)
 100 NEXT a
  
 105 PLOT 39,152: DRAW PAPER 5;177,0: DRAW PAPER 5; 0,-145: DRAW PAPER 5;-177,0: DRAW PAPER 5;0,145
 
 110 DEF FN b(x)=INT(x/256)
 120 DEF FN a(x)=x-(INT(x/256)*256)

 130 GO SUB 9000
 140 RANDOMIZE USR 64000
 145 PRINT AT 0,11;"PEEK ";PEEK 63000;" ";PEEK 63001;" ";PEEK 63002
 150 PAUSE 0
 160 STOP

9000 DIM p(2)
9010 LET p(1)=63000
9020 LET p(2)=62000
9030 FOR f=0 TO 1
9040 RESTORE 9100
9044 LET r=p(f+1)
9045 LET ra=FN a(r): LET rb=FN b(r)
9046 PRINT AT f,0;ra;" : ";rb
9050 FOR n=64000+(f*25) TO 64024+(f*25)
9060 READ q
9070 POKE n,q
9080 NEXT n
9085 NEXT f
9090 RETURN

9100 DATA 17,ra,rb
9110 DATA 33,FN a(22629),FN b(22629)
9120 DATA 6,18
9130 DATA 197
9140 DATA 6,22
9150 DATA 26,119,19,35
9160 DATA 16,249
9170 DATA 1,10,0
9180 DATA 9
9210 DATA 193
9220 DATA 16,240
9230 DATA 201
There is a loop which loads the buffer memory addresses with an alternating black and red paper value. This is working fine as the two printed PEEK's will show. My routine is changing attributes within the window in the correct locations but the attribute data is not correct. In my output window I get stripes of the same attribute, each line is a random attribute. I am having difficulty with the image posting at the moment so unfortunately I cannot upload a screen grab.

Can anyone help me? I may not have presented the question well, please tell me how I can improve if this is so.

Edit :

Link to the magazine article : Page 17

Edit :

Added parenthesis to LD A,(DE)
Last edited by MonkZy on Fri Feb 23, 2018 1:49 pm, edited 1 time in total.
AndyC
Dynamite Dan
Posts: 1388
Joined: Mon Nov 13, 2017 5:12 am

Re: New to machine code...seeking assistance.

Post by AndyC »

I think you mean LD A, (DE) rather than LD A,DE. Also I'm not sure your second relative jump offset is calculated correctly (which is why an assembler and labels makes this lots easier to debug)
Ralf
Rick Dangerous
Posts: 2279
Joined: Mon Nov 13, 2017 11:59 am
Location: Poland

Re: New to machine code...seeking assistance.

Post by Ralf »

Hi, some quick advice:
DJNZ,-11
I definitely advise you to use labels

LD B,256
it should give you compiler error as register can be from 0 to 255

33,0,64 LD HL,16384
Personally I wouldn't care about the codes for instructions. You don't need to know them for 99% of time. The assembler will generate
them for you.
Of course unless you write your asm programs as DATA 33,0,64 in Basic. But it would be pure masochism in 2018 ;)
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: New to machine code...seeking assistance.

Post by MonkZy »

Agreed ralf. I am sure that the problem lies in the DJNZ jumps, it appears to be missing the instruction LD a,(de) in the first loop. I guess working from a hand compiled magazine routine is not a great approach to learning assembly. I think the author wanted 256 cycles on the first loop so started LD b,0..this is not easy to see in the mnemonics. I am guessing the DJNZ instruction will loop if the b register is already set to zero , resulting in the b register holding 255.

OK..I will re-visit the z80asm command. I have been playing with z80asm combined with bin2tap, but it all seemed very awkward to rapidly build and test. I am using fuse in linux.
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: New to machine code...seeking assistance.

Post by MonkZy »

Andy C, yarp it is LD A,(DE) as I discovered when looking up the codes in the back of the BASIC manual...the code from the magazine is a bit a sloppy and I have copied this :o
Ralf
Rick Dangerous
Posts: 2279
Joined: Mon Nov 13, 2017 11:59 am
Location: Poland

Re: New to machine code...seeking assistance.

Post by Ralf »

I think the author wanted 256 cycles on the first loop so started LD b,0..this is not easy to see in the mnemonics
Yes, it's a known trick. Set loop counter to zero so loop executes 256 times. Although it may be a bit confusing for a beginner, I would leave it for intermediate course ;)
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: New to machine code...seeking assistance.

Post by Nomad »

I used to do it in byte code but debugging is a pita that way. You can spend hours trying to track down a bug that is trivial to see if you are using mnemonics. Still if you were using the contemporary magazines/books that was the assumed way to use it..

Once you get the hang of the assembler the workflow gets much faster. You can pick any it is really a personal choice - but some are better than others.

For me its a toss up between zeus and pasmo. They are both very nice to use.

If you like IDE and lots of support, plus a bit more hand holding via scripting then Zeus is going to be your bag. Its got everything you could want to create a game all in one place. About the only thing extra you would need is zxpaintbrush and possibly SevenuP, oh and beepola. Then you would be all set to conquer the world.

You can tackle big projects better with Zeus I would say. As it forces you to script the build process from the jump start. With Pasmo you can be more messy. But its quicker to get going with.

If you like things basic, with more a command line type of guy. Then go for Pasmo. It does not have all of the extra stuff that Zeus has but its still good if you want a solid assembler that you can quickly develop programs with. You can assemble and generate the tap or tzx file in one go.

Code: Select all

 pasmo --tapbas UberCode.asm UberCode.tap 

Code: Select all

 pasmo --tzxbas UberCode.asm UberCode.tzx 
Badabing badaboom you are done.

You could even put it in a batch file/script and make it even more fast... most have it set up so you can either click on the editor or hit a key to assemble, create the tap and run the tap in an emulator. That way you can see what you are doing extremely quickly, bounce back to the editor from the emulator and make adjustments. click do the same thing again and repeat.
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: New to machine code...seeking assistance.

Post by MonkZy »

Cheers guys, your support has been most appreciated.

I wrote the routine in proper assembly as follows :

Code: Select all

; Attribute shifting routine

org 34000

start:
ld de,63000
ld hl,22629

ld b,18

loop1:
push bc
ld b,22

loop2:
ld a,(de)
ld (hl),a
inc de
inc hl
djnz loop2

ld bc,10
add hl,bc
pop bc
djnz loop1
ret
I ran this code through z80asm, then converted the .bin to a .tap using the basic loader option in BIN2TAP.EXE. Bosh. Worked first time.

I am writing a crap game for the cgc. It will be mostly BASIC with maybe one or two machine code routines. I will need to faff about loading code from files and I am sure I will run into difficulties. My first approach was the old-skool 'bung the code into a DATA line', but now I am elevated to using an assembler. I have looked at Zeus and let us say I was a tad overwhelmed plus it runs in WINE and looks ghastly. I will check out Pasmo next, sounds like my kind of thing. Zues looks great though and I will return to it.

Cheers again for the tips and support.

Edit: Indicated I had used BIN2TAP.EXE
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: New to machine code...seeking assistance.

Post by Nomad »

Yea most applications under wine look pants, I think its because wine can't link to the proper fonts the apps you are trying to emulate want.

If its running with tiny fonts (that's the issue I had) I solved it like this..

Code: Select all

Type "wine regedit" in a terminal. Then navigate to HKEY_CURRENT_CONFIG > Software > Fonts and change the LogPixels setting I set mine to 100 (decimal) and it looks ok, l
ittle bit windows 3.1ish but its ok.

There is another way to set it via config but I forget.

You can run zeus as a stand alone assembler from the command line, that was one way I was going to use it with scripts just like pasmo then but with all the build support you get with zeus.

I can tell you now the crippling thing with pasmo is you will get to a point where you want to do a big project, define macros or use local variables then the pain starts. I think at that point its seriously a good idea to look at Zeus.

That said plenty of folks have done impressive stuff with pasmo. It's like a marmite/vi/emacs type deal. Some people love it or hate it.

With the crap game, it might be a challenge to do the whole thing in assembly, I find it easier than trying to call machine code from basic. Plus you get the freedom to structure the program as you like where you like doing it that way.

Good luck with the project!
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: New to machine code...seeking assistance.

Post by RMartins »

If you are just copying, you can use LDIR instruction instead of:

Code: Select all

ld a,(de)
ld (hl),a
inc de
inc hl
Just make sure you set BC, to 22, before hand.
Bizzley
Microbot
Posts: 124
Joined: Thu Nov 16, 2017 10:47 am

Re: New to machine code...seeking assistance.

Post by Bizzley »

I would not reccomend the PASMO assembler if you are just starting off with assembly. It does not validate numbers after commands properly which can lead to unexpected results e.g. the following program will quite happily assemble under PASMO with no errors being generated:

Code: Select all

	org 327689
	ld a,456
	ld hl,123456789
	ld (hl),a
loop: jp loop
and will actually create a valid object file. However the contents will be:

Code: Select all

	ld a,200
	ld hl,52501
	ld (hl),a
	jp 15
Once you realize that PASMO assembles all 8 bit numbers as modulo 256 and 16 bit numbers as modulo 65536 - even the incorrect ones - then it makes sense, but it's so easy to mis-type a number or accidentally enter something that should be out of bounds that the least an assembler should do is flag it as a warning. Once you are more confident in your coding abilities then this shouldn't be a problem but when you are just starting to learn machine code you shouldn't have to worry that your assembler is hindering your efforts instead of helping you.
"He made eloquent speeches to an audience consisting of a few depressed daffodil roots, and sometimes the cat from next door."
Post Reply