my first ASM program lol

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

my first ASM program lol

Post by Jbizzel »

Hi,

Well, I've been messing about in ASM and actually managed to compile something using Pasmo. Its not very exciting, but its a start.

All is sort of well.... but, if I compile with the diamond UDG the program seems to hang at the end, but if I compile with the dog UDG the program runs and returns to basic as I'd expect. It seems such a weird problem it has me stumped! Any ideas?

Also, I have no idea how you are supposed to do such a task as this program performs, so I'm probably doing it in a weird and wonderful way. But hey, I only know LD, INC, DEC, PUSH, POP, JP, DJNZ :lol:
Spoiler

Code: Select all


org 32768

ld c,$08
ld hl,$4000    
push hl
ld b,$03
ld de,udg   
jp fill32
fill8: 
ld a,b   
ld b,$3
ld c,a
fill32:
push bc     
ld b,256    
loop:        
ld a,(de)   
ld (hl),a    
inc l         
DJNZ loop   
ld a,h      
add a,$08 
ld h,a 
pop bc 
DJNZ fill32 
inc de 
pop hl 
inc h 
push hl
ld b,c 
DJNZ fill8

RET

udg: 
defb $10, $38, $7C, $FE, $7C, $38, $10, $00 ; diamond 
;defb $10, $F0, $D1, $FF, $7F, $7F, $7F, $55 ; a dog
end 32768
Image
User avatar
Mpk
Dynamite Dan
Posts: 1008
Joined: Tue Feb 09, 2021 8:10 am

Re: my first ASM program lol

Post by Mpk »

Jbizzel wrote: Sun Sep 04, 2022 8:31 pm if I compile with the diamond UDG the program seems to hang at the end, but if I compile with the dog UDG the program runs and returns to basic as I'd expect.
This may be gender-based. If you're a gent, try to get a lady to compile it and see what happens. Results should be reversed, as while a dog is man's best friend, diamonds are a girl's best friend.
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

Mpk wrote: Sun Sep 04, 2022 8:42 pm This may be gender-based. If you're a gent, try to get a lady to compile it and see what happens. Results should be reversed, as while a dog is man's best friend, diamonds are a girl's best friend.
Genius 😂

I line 'em up, and you knock 'em down! 😂😂

But seriously, what on earth is going on?
User avatar
Spud
Manic Miner
Posts: 375
Joined: Sun Nov 12, 2017 8:50 pm
Contact:

Re: my first ASM program lol

Post by Spud »

You're probably shagging the stack at the end and returning to somewhere weird. That last push hl doesn't have a pop later to fix it.
User avatar
Bedazzle
Manic Miner
Posts: 305
Joined: Sun Mar 24, 2019 9:03 am

Re: my first ASM program lol

Post by Bedazzle »

I do not use Pasmo, but it is kinda weird, if at compile time it does not warn you about
ld b,256
because B can't hold value 256.

Don't know about exit to basic (usually it is a problem, if sysvars, alternative registers or IY are destroyed), but I'd write something like this based on your source:

Code: Select all

	org 32768
	
code_start:
	ld hl, $4000

	ld c, 3
fill_three:
	ld de, udg
	ld b, 8
fill:
	ld a, (de)
loop:
	ld (hl), a
	inc l
	jr nz, loop
	
	inc h
	inc de
	djnz fill
	dec c
	jr nz, fill_three
	
	ret

udg: 
	defb $10, $38, $7C, $FE, $7C, $38, $10, $00 ; diamond 
	;defb $10, $F0, $D1, $FF, $7F, $7F, $7F, $55 ; a dog
User avatar
PeterJ
Site Admin
Posts: 6879
Joined: Thu Nov 09, 2017 7:19 pm
Location: Surrey, UK

Re: my first ASM program lol

Post by PeterJ »

@Jbizzel,

I'm a very amateur coder, but can I suggest something simpler?

Code: Select all

	ORG 30000
	LD A,2			
	CALL 5633
	LD HL,GFX		
	LD (23675),HL		
	LD BC,768
LP:	DEC BC
	LD A,144		
	RST 16			
	LD A,B
	OR C
	JR NZ, LP
	RET
GFX	DEFB 16,240,209,255,127,127,127,85
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

Spud wrote: Sun Sep 04, 2022 9:34 pm You're probably shagging the stack at the end and returning to somewhere weird. That last push hl doesn't have a pop later to fix it.
it was the POP! or lack of. Thanks @Spud
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

PeterJ wrote: Sun Sep 04, 2022 10:11 pm @Jbizzel,

I'm a very amateur coder, but can I suggest something simpler?
much simpler I'll take a look at this. I did get a scroll when I compiled it though. Thank you for your help :)

I see you are using a call, so this is using the basic routine to draw the UDG perhaps?
User avatar
PeterJ
Site Admin
Posts: 6879
Joined: Thu Nov 09, 2017 7:19 pm
Location: Surrey, UK

Re: my first ASM program lol

Post by PeterJ »

@Jbizzel

That call just sets the output to be directed to the main screen (after loading a with 2).

The RST16 is the ROM routine for printing, just load A with the character and RST16 will print it. You can also print the control codes.

The BC loop gets around the issue of looping more than 255 times.

The purists, generally discourage the use of ROM routines, but each to their own.

Edit. Having thought about it overnight. Because I'm using the ROM Print routine and calling 5633 with 2, it's only printing 21 lines (theres scrolling because it's looping 768 times rather than 704). Your solution is much smarter directly altering the screen memory.
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

Bedazzle wrote: Sun Sep 04, 2022 9:45 pm I do not use Pasmo, but it is kinda weird, if at compile time it does not warn you about
ld b,256
because B can't hold value 256.

Don't know about exit to basic (usually it is a problem, if sysvars, alternative registers or IY are destroyed), but I'd write something like this based on your source:
Thank you! very interesting, its based on my code but without the mess!

JR NZ was the only additional instruction - Jump when Z is reset I'm guessing.

I guess I was making my life hard by only using DJNZ for everything and having to juggle what was on B like mad!
User avatar
flatduckrecords
Manic Miner
Posts: 787
Joined: Thu May 07, 2020 11:47 am
Location: Oban, Scotland
Contact:

Re: my first ASM program lol

Post by flatduckrecords »

Congrats @Jbizzel! Is this inspired by reading the Hewson book? :ugeek:

To help with debugging you could try setting a breakpoint in your code, then stepping through the routine one line at a time. I found that really helpful to understanding what’s going on, even if it’s just comparing what you think should happen vs what’s actually happening!

Which emulator do you use? E.g in Fuse you open up the debugger and “evaluate” a command to set a breakpoint:

Code: Select all

BR 0x8000
That will wait for the code at 32768 to run, and then immediately pause at that point. You can then single-step through each instruction and observe the values of the registers, and (related to what @Spud was saying) see what values are on the stack. (I agree that’s probably where the problem is!)
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

Thanks @flatduckrecords

I do use fuse, and loaded the debugger even, but had no idea about breakpoints or how to debug!

I have got the code working now which is great. Although I'm also thinking once it runs I can't currently call it again from basic, so I have probably got to do something else to not mess up the code from that perspective?

Yes, reading the book on the train and working though a couple of examples with pen and paper gave me the bug again.

What I had in mind was filling the screen, then adapting the code to draw a level. I was thinking of working towards a manic miner type game. The 8x8 blocks making up the levels.

So it was interesting to see @Joefish 's thread on here about the optimising challenge too. Although I haven't quite got my head around their examples yet.

What are interleaved graphics! 😬😁 One step at a time I guess
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

Bedazzle wrote: Sun Sep 04, 2022 9:45 pm I do not use Pasmo, but it is kinda weird, if at compile time it does not warn you about
ld b,256
because B can't hold value 256.
This is interesting, like how does my code even work in that case 😂😂😂

I assume it's doing something like 255 to 0 for the loop, which is probably what I need even though I asked it to do something impossible!
User avatar
flatduckrecords
Manic Miner
Posts: 787
Joined: Thu May 07, 2020 11:47 am
Location: Oban, Scotland
Contact:

Re: my first ASM program lol

Post by flatduckrecords »

Jbizzel wrote: Sun Sep 04, 2022 11:24 pm I assume it's doing something like 255 to 0 for the loop, which is probably what I need even though I asked it to do something impossible!
I’m not sure whether Pasmo has a “listing” option? I use SjASMPlus—if you assemble with the “ -lst ” option it will generate an extra file that has the assembly language right next to the assembled machine code bytes, line for line, so you can see how the assembler has interpreted your code. Or indeed look in the Fuse debugger and see what value it’s using. I think the listing gives memory addresses too, so you can refer to that if you want to set specific breakpoints.
Matt_B
Manic Miner
Posts: 659
Joined: Sun Nov 01, 2020 8:47 am

Re: my first ASM program lol

Post by Matt_B »

For what it's worth, loading b with 0 is exactly what you want for a DJNZ loop that iterates 256 times.

The first time it gets to the instruction, b is decremented, wrapping around to the value of 255. This isn't zero, so it'll go round the loop another 255 times.

There are a lot of other instances where wanting to load b with 256 rather than 0 is just a brain fart though, so an assembler should probably at least give a warning for it.
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

thanks @Matt_B That's great to know, and I've amended my code accordingly.

So here is a bit of code from @Pobulous in the other thread https://www.spectrumcomputing.co.uk/for ... 3&start=10 which I had a question about...

The AND A here is used to set or reset Z for the next instruction, is that correct?

(for the conditional jump that follows it)

Code: Select all

PrintLoop:
			LD A,(HL)		;Get next CharMap character to print
					
			AND A			;if zero, skip over screen position 
			JP Z, SkipPrinting ; if a = 0 jump
User avatar
Cosmium
Microbot
Posts: 156
Joined: Tue Dec 04, 2018 10:20 pm
Location: USA

Re: my first ASM program lol

Post by Cosmium »

Jbizzel wrote: Mon Sep 05, 2022 9:11 pm The AND A here is used to set or reset Z for the next instruction, is that correct?

(for the conditional jump that follows it)
That's right. The AND A instruction sets or resets the Z flag depending on the value of A.

In this case it's used in conjunction with the following JP Z to skip printing if A (the character to print) is 0.

As a side note, AND A can also be used to clear the carry flag (with SCF being use to set it).
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

So this is another interesting section of code... again from @Pobulous in the other thread.

Here CP 9 sets C flag if A is < 9

This then relates to this: JP C,PrintATTROnly which means that a section of code is skipped over if A < 9.

I really don't get this bit though! "LD H,UDGs/256" Is it literally UDG getting divided by 256? Can't be can it?

Code: Select all

CP 9			;chars 1-(n-1) (1-8 in this case) will only update attr data (set to 0 or 1 to disable this feature)
			
			PUSH HL			;Store CharMap location
			LD H,UDGs/256	;Get base address of UDGs
			LD L,A			;Select UDG 1-255
			LD A,(HL)		;copy ATTR data
			LD (BC),A
			
			JP C,PrintATTROnly ; see line 16 above, if A < 9 then jump
azesmbog
Manic Miner
Posts: 307
Joined: Sat May 16, 2020 8:43 am

Re: my first ASM program lol

Post by azesmbog »

Jbizzel wrote: Mon Sep 05, 2022 10:55 pm "LD H,UDGs/256" Is it literally UDG getting divided by 256? Can't be can it?
in decent assemblers there is such a construction:
low - low x - low 8 bits of 16 bit value or lower part of register pair
high - high x - high 8 bits of 16 bit value or higher part of register pair

in this case it would look like this:

Code: Select all

LD H,HIGH UDGs
so much clearer?
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

thanks @azesmbog I just swapped the code and compiled with Pasmo, and indeed LD H,HIGH UDGs works.

so if the data is 1111111100000000 for example then

LD H,HIGH would set H to 11111111

or

LD H,LOW would set H to 00000000
azesmbog
Manic Miner
Posts: 307
Joined: Sat May 16, 2020 8:43 am

Re: my first ASM program lol

Post by azesmbog »

So dividing a 16-bit number by 256 just gives the same thing, the highest part.
Therefore, you can use it this way and that, a matter of habit and taste)
User avatar
uglifruit
Manic Miner
Posts: 703
Joined: Thu Jan 17, 2019 12:41 pm
Location: Leicester
Contact:

Re: my first ASM program lol

Post by uglifruit »

Jbizzel wrote: Sun Sep 04, 2022 8:31 pm Well, I've been messing about in ASM and actually managed to compile something using Pasmo. Its not very exciting
Yes it is exciting. It's always exciting getting asm working.
CLEAR 23855
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

So, my process is examine the code examples and work through them until I understand what others have done, then start with a blank sheet and try to fly solo.

For the code below I thought Id try something different. This code:

- Starts top right rather than top left
- fills a whole attribute at a time
- moves down the screen a row at a time

Now I have learnt more about using conditional jumps rather than trying to juggle different counters on the B like my very first attempt.

Code: Select all

org 32768

ld hl, $401f ; load scree address
ld c,0 ; 256 counter

drawudg:

ld de,udg   ; store source

ld b,8      ; loop 8 times
loop:    ; loop back here
ld a,(de)   ; load source
ld (hl),a   ; copy to screen
inc de      ; next source byte
inc h       ; next line of char
DJNZ loop   ; b=b-1, if b <> 0 loop.

dec l
ld a,h 
sub 8 
ld h,a
dec c
jr nz, drawudg

ld a,h       ; move to next part of screen
add a, 8 
ld h,a

CP $58			
JP C, drawudg	          ;Do next screen third

RET
User avatar
Pobulous
Dynamite Dan
Posts: 1366
Joined: Wed Nov 15, 2017 12:51 pm

Re: my first ASM program lol

Post by Pobulous »

With regards the LD H,UDGs/256, it's worth clarifying that this expression is only evaluated by the assembler at the time of assembly - at runtime it will just be a constant value.
User avatar
Jbizzel
Dynamite Dan
Posts: 1537
Joined: Mon May 04, 2020 4:34 pm
Location: Hull
Contact:

Re: my first ASM program lol

Post by Jbizzel »

Just having fun with these routines to help me embed my understanding hopefully! Here is a program that can be used in basic to turn a different font on or off.

Code: Select all

10 poke 40000,1
20 randomize usr 32768
30 print "hello"

Code: Select all

org 32768

ld a,(flag)  ;check flag to see if we will change the font
AND a        ; is a 0?
JP Z, skip   ; if so skip changing the font

ld hl,typeface-256   ; load a new font
ld (23606),hl
jp done

skip:             ; this will allow us to turn off the new font.
ld hl,15616-256
ld (23606),hl

done:

ret

org 40000
flag
defb 0

typeface: ; a font from DamienG https://damieng.com
  defb 000h,000h,000h,000h,000h,000h,000h,000h ;  
  defb 000h,038h,038h,038h,000h,038h,000h,000h ; !
  defb 000h,06ch,06ch,06ch,000h,000h,000h,000h ; "
  defb 000h,06ch,0feh,06ch,0feh,06ch,000h,000h ; #
  defb 000h,018h,07eh,078h,01eh,07eh,018h,000h ; $
  defb 000h,072h,074h,018h,02eh,04eh,000h,000h ; %
  defb 000h,07eh,070h,03eh,06ch,07eh,000h,000h ; 0
  defb 000h,018h,018h,018h,000h,000h,000h,000h ; '
  defb 000h,03ch,070h,070h,07ch,03ch,000h,000h ; (
  defb 000h,03ch,00eh,00eh,03eh,03ch,000h,000h ; )
  defb 000h,018h,07eh,03ch,07eh,018h,000h,000h ; *
  defb 000h,000h,038h,0feh,038h,000h,000h,000h ; +
  defb 000h,000h,000h,000h,018h,018h,018h,000h ; h,
  defb 000h,000h,000h,07ch,000h,000h,000h,000h ; -
  defb 000h,000h,000h,000h,030h,030h,000h,000h ; .
  defb 000h,00ch,01ch,038h,070h,060h,000h,000h ; /
  defb 000h,07eh,076h,076h,07eh,07eh,000h,000h ; 0
  defb 000h,078h,018h,018h,07eh,07eh,000h,000h ; 1
  defb 000h,07eh,00eh,038h,07eh,07eh,000h,000h ; 2
  defb 000h,07eh,00eh,03ch,00eh,07eh,000h,000h ; 3
  defb 000h,03ch,05ch,07eh,07eh,01ch,000h,000h ; 4
  defb 000h,07eh,070h,07eh,00eh,07ch,000h,000h ; 5
  defb 000h,07eh,070h,07eh,076h,07eh,000h,000h ; 6
  defb 000h,07eh,00eh,00eh,01ch,01ch,000h,000h ; 7
  defb 000h,07eh,076h,03ch,06eh,07eh,000h,000h ; 8
  defb 000h,07eh,06eh,07eh,00eh,07eh,000h,000h ; 9
  defb 000h,000h,018h,000h,018h,018h,000h,000h ; :
  defb 000h,000h,018h,000h,018h,018h,018h,000h ;h ;
  defb 000h,01ch,038h,070h,038h,01ch,000h,000h ; <
  defb 000h,000h,07ch,000h,07ch,000h,000h,000h ; =
  defb 000h,038h,01ch,00eh,01ch,038h,000h,000h ; >
  defb 000h,07eh,00eh,03ch,000h,038h,000h,000h ; ?
  defb 000h,07eh,06eh,06eh,060h,07eh,000h,000h ; @
  defb 000h,07eh,06eh,07eh,06eh,06eh,000h,000h ; A
  defb 000h,07eh,076h,07ch,076h,07eh,000h,000h ; B
  defb 000h,07eh,070h,070h,07eh,07eh,000h,000h ; C
  defb 000h,07ch,076h,076h,07eh,07eh,000h,000h ; D
  defb 000h,07eh,070h,07eh,078h,07eh,000h,000h ; E
  defb 000h,07eh,070h,07eh,070h,070h,000h,000h ; F
  defb 000h,07eh,070h,076h,07eh,07eh,000h,000h ; G
  defb 000h,076h,076h,07eh,076h,076h,000h,000h ; H
  defb 000h,038h,038h,038h,038h,038h,000h,000h ; I
  defb 000h,00eh,00eh,06eh,07eh,07eh,000h,000h ; J
  defb 000h,076h,076h,07ch,07eh,076h,000h,000h ; K
  defb 000h,070h,070h,070h,07eh,07eh,000h,000h ; L
  defb 000h,0c6h,0eeh,0feh,0feh,0d6h,000h,000h ; M
  defb 000h,066h,076h,07eh,07eh,076h,000h,000h ; N
  defb 000h,07eh,076h,076h,07eh,07eh,000h,000h ; O
  defb 000h,07eh,076h,07eh,07eh,070h,000h,000h ; P
  defb 000h,07eh,076h,076h,07eh,07eh,00eh,000h ; Q
  defb 000h,07eh,076h,07ch,07eh,076h,000h,000h ; R
  defb 000h,07eh,070h,07eh,00eh,07eh,000h,000h ; S
  defb 000h,0feh,038h,038h,038h,038h,000h,000h ; T
  defb 000h,076h,076h,076h,07eh,07eh,000h,000h ; U
  defb 000h,076h,076h,076h,07ch,078h,000h,000h ; V
  defb 000h,0c6h,0d6h,0feh,0feh,0eeh,000h,000h ; W
  defb 000h,076h,07eh,03ch,07eh,06eh,000h,000h ; X
  defb 000h,076h,076h,07eh,00eh,07eh,000h,000h ; Y
  defb 000h,07eh,01ch,038h,07eh,07eh,000h,000h ; Z
  defb 000h,07eh,070h,070h,07eh,07eh,000h,000h ; [
  defb 000h,060h,070h,038h,01ch,00ch,000h,000h ; \
  defb 000h,07eh,00eh,00eh,07eh,07eh,000h,000h ; ]
  defb 000h,018h,03ch,07eh,03ch,03ch,000h,000h ; ^
  defb 000h,000h,000h,000h,000h,000h,07eh,000h ; _
  defb 000h,07eh,072h,07ch,070h,07eh,000h,000h ; £
  defb 000h,000h,07eh,06eh,07eh,076h,000h,000h ; a
  defb 000h,070h,07eh,076h,07eh,07eh,000h,000h ; b
  defb 000h,000h,07eh,060h,07eh,07eh,000h,000h ; c
  defb 000h,00eh,07eh,06eh,07eh,07eh,000h,000h ; d
  defb 000h,000h,07eh,076h,07ch,07eh,000h,000h ; e
  defb 000h,01eh,01ch,03eh,01ch,01ch,000h,000h ; f
  defb 000h,000h,07eh,06eh,07eh,00eh,07eh,000h ; g
  defb 000h,070h,07eh,076h,076h,076h,000h,000h ; h
  defb 000h,038h,000h,038h,038h,038h,000h,000h ; i
  defb 000h,01ch,000h,01ch,01ch,01ch,03ch,000h ; j
  defb 000h,070h,076h,07ch,076h,076h,000h,000h ; k
  defb 000h,03ch,01ch,01ch,01ch,01ch,000h,000h ; l
  defb 000h,000h,0eeh,0feh,0feh,0d6h,000h,000h ; m
  defb 000h,000h,07eh,076h,076h,076h,000h,000h ; n
  defb 000h,000h,07eh,076h,07eh,07eh,000h,000h ; o
  defb 000h,000h,07eh,076h,07eh,07eh,070h,000h ; p
  defb 000h,000h,07eh,06eh,07eh,07eh,00eh,000h ; q
  defb 000h,000h,07eh,076h,070h,070h,000h,000h ; r
  defb 000h,000h,07eh,078h,01eh,07eh,000h,000h ; s
  defb 000h,038h,07eh,038h,03eh,03eh,000h,000h ; t
  defb 000h,000h,076h,076h,076h,07eh,000h,000h ; u
  defb 000h,000h,076h,076h,07ch,078h,000h,000h ; v
  defb 000h,000h,0d6h,0feh,0feh,0eeh,000h,000h ; w
  defb 000h,000h,076h,03ch,07eh,06eh,000h,000h ; x
  defb 000h,000h,06eh,06eh,07eh,00eh,07eh,000h ; y
  defb 000h,000h,07eh,01eh,078h,07eh,000h,000h ; z
  defb 000h,01eh,01ch,078h,01ch,01eh,000h,000h ; {
  defb 000h,038h,038h,038h,038h,038h,000h,000h ; |
  defb 000h,078h,038h,01eh,038h,078h,000h,000h ; }
  defb 000h,076h,06eh,000h,000h,000h,000h,000h ; ~
  defb 07fh,041h,03eh,030h,03eh,03eh,041h,07fh ; ©

end 32768
Image
Post Reply