Z80 assembly question

kstillin

Well-known member

Donor 2018
Joined
Aug 24, 2006
Messages
4,698
Reaction score
130
Location
Columbia, South Carolina
Hey-

I'm looking at a program disassembly and have seen something funky in a couple of places.
Code:
03EA: AF             XOR   A,A
03EB: 57             LD    D,A
[b]03EC: 72             LD    (HL),D
03ED: 72             LD    (HL),D[/b]
03EE: 23             INC   HL
03EF: 0B             DEC   BC
03F0: 78             LD    A,B
03F1: B1             OR    A,C
03F2: 20 F8          JR    NZ,$03EC

03F4: C9             RET

I can tell that this is clearing out a block pointed to by HL for BC count of bytes.

What's the point of the apparently double load statement? D is a single byte being loaded into the location pointed to by HL, right? I don't get the repeated LD statement.
I've seen it in more that one block of code and I'm thinking there may be some quirk that I'm unaware of.

Any help is appreciated.
Kerry
 
I considered that, but thought this may be something peculiar to Z80.

Thanks- actually, I was going to PM you directly. Funny that you wound up answering!
 
My z80 is pretty rusty, but it could be the initial load clears the hardware registry, or initialises before reading.

Where did you find the code and what hardware does it run on?
 
Yeah and be sure you'r actually looking at disassembled code and not disassembled data. I make that mistake sometimes when I neglect to look at the memory map and just blatantly disassemble the entire address range.
 
Yeah and be sure you'r actually looking at disassembled code and not disassembled data. I make that mistake sometimes when I neglect to look at the memory map and just blatantly disassemble the entire address range.

True. But the given code just looks (to me) like it makes way too much sense to be a wacky coincidence with data... aside from the repeated instruction.
 
True. But the given code just looks (to me) like it makes way too much sense to be a wacky coincidence with data... aside from the repeated instruction.

Yeah, that code snippet has way too much intelligence to be random....
Separating code and data can be a challenge at times (they are often intermingled, so a memory map is not going to help you), but in this case we're clearly looking at code.
 
you are looking at a delay routine.

find referencing code, you should see the BC registers loaded.

then a call into it.

the
xor a,a
ld d,a

is an initial delay,

the ld(hl),d are just an added delay.

when the routing is done.

HL will be 1
BC will be 0
 
I'm looking at some program code for Jungle King.

This is the first time I've really dug into some of it.
I used to do some 68HC11 assembly way back in college and had tinkered with Intel 8086 stuff, but it's been a long time.

I never messed with any Z80 code, but most of this stuff is the same. Sitting down with the memory map from Mame and a schematic helps too.

It is neat to uncover the strings sitting right there with the code.

Code:
060A: 19 1E 1C 11    -- data   P U S H
060E: 18 17 15 22 ff ff 01 19 15 0A 22 0E 1B FF 0B 1E 1D 1D 18 17
      O  N  L  Y  -  -  1  P  L  A  Y  E  R  -  B  U  T  T  O  N
You can see it reading from the mapped ports and checking bits to see if buttons are pressed. You can see it checking specific memory locations and branching in different cases. It's neat to figure out what a memory location is storing based on what the code is doing to it.

I don't have a real goal yet. It would be kind of neat to decipher everything, but there is just so much of it. So many calls and jumps and little routines that just seem like spaghetti.

There are some other games that I'd like to figure out some of the game logic, but I started here.
Thanks for the pointers. Right now, I'm just using a simple disassembler and making notes.

Kerry
 
you are looking at a delay routine.
I'm not sure I agree.
find referencing code, you should see the BC registers loaded.

then a call into it.

Finding code calling this routine would be very useful. I'd expect to see the HL loaded as well as BC.

the
xor a,a
ld d,a

is an initial delay,

I interpret a little differently:
XOR A,A ; is a single byte way to set the accumulator to 0
LD D,A ; also puts 0 in the D register

the ld(hl),d are just an added delay.

It places D (which is 0) into the memory location pointed to by HL.
The question is, why do it twice?

when the routing is done.

HL will be 1
BC will be 0

HL will not necessarily be 1 at the end; it will be incremented once each time thru the loop, and the loop will execute BC times (the value of BC when this subroutine is called).

I agree what BC will be 0 when it RETurns.
 
03EA: AF XOR A,A
03EB: 57 LD D,A
03EC: 72 LD (HL),D
03ED: 72 LD (HL),D
03EE: 23 INC HL
03EF: 0B DEC BC
03F0: 78 LD A,B
03F1: B1 OR A,C
03F2: 20 F8 JR NZ,$03EC

03F4: C9 RET

So,

XOR A,A ; A=0 Variable initialization to 0
LD D,A ; D=0 Variable initialization to 0

DO LOOP ; next line is code address $03EC and is the start of our loop code
LD (HL),D ; value of memory location (HL) = 0;
LD (HL),D ; value of memory location (HL) = 0; timing, or coder though he had to do it twice - once for low order byte, and once again for high order byte.

INC HL ; Point to next memory location
DEC BC ; decrease value of 16-bit register BC by 1
LD A,B ; A = contents of B register - whatever that may be after preceeding DEC
OR A,C ; If A != 0 OR C != 0, then set proper flag.
WHILE ; End of loop, if A != 0 OR if C != 0, go back to top of DO LOOP

RET ; Both A=0 AND C=0, breaking us out of loop, we can return now.

We never saw what register BC (or B then C) got loaded with (nor did we see what HL was loaded with...), so we can't tell how many loop interations we did. Check further up in the code to see what BC got loaded with - possibly a constant.

All this does is clear the BC bytes of memory to 0. The memory starts at address HL and moves up to HL + the initial value of BC bytes.
 
Last edited:
Let me correct myself :)

this routine is being used to clear a block of memory from the Address FROM HL to HL+BC

if BC = 0x0010
if HL = 0x7000

this route would CLEAR (or set to ZERO)

Address 0x7000 - 0x7010

i think it does the LD (HL),D twice to make sure the RAM took the write (maybe some ext ram needs the write to be called twice? once to load the address, once to write it?)
 
Last edited:
Let me correct myself :)

this routine is being used to clear a block of memory from the Address FROM HL to HL+BC

if BC = 0x0010
if HL = 0x7000

this route would CLEAR (or set to ZERO)

Address 0x7000 - 0x7010

i think it does the LD (HL),D twice to make sure the RAM took the write (maybe some ext ram needs the write to be called twice? once to load the address, once to write it?)


Basically, i just said what hypersport said ....
 
I don't know... to me it looks like it might be part of a data section. Hard to tell from that small snippit
 
Back
Top Bottom