Need help with Z80 code

Discussion in 'Embedded Systems and Microcontrollers' started by AldoLinklot, May 6, 2009.

  1. AldoLinklot

    Thread Starter New Member

    May 6, 2009
    FYI! This is for a school project. I just need some guidance as my instructor seems uninterested.

    I have to write some code for the Z80 that will execute two instructions then copy those instructions to 2000H then goto 2000H and execute those instructions there then return to the original program and delete the instructions that were copied to 2000H

    Here is what we start with:

    Code ( (Unknown Language)):
    1. ORG 1800H
    3. ADD A,B
    4. ADD A,C
    5. NOP
    6. NOP
    7. NOP
    8. NOP
    9. NOP
    10. NOP
    11. NOP
    12. NOP
    13. NOP
    14. NOP
    15. NOP
    16. NOP
    17. HALT
    I have to replace the NOP's with the new instructions.

    Here is where I am:

    Code ( (Unknown Language)):
    2.   ORG 1800H
    3.   ADD A,B
    4.   ADD A,C
    5.   LD  A,(1800H)
    6.   LD  (2000H),A
    7.   LD  A,(1801H)
    8.   LD  (2001H),A
    9.   ORG 2000H
    10.   ORG 180EH
    11.   LD  A,00H
    12.   LD  (2000H),A
    13.   LD  (2001H),A
    14.   HALT
    My problem is after copying the opcode to 2000H and 2001H and then going there using ORG 2000H, I dont know how to make the instructions in that memory actually execute before returning to 180EH.

    Can anyone give me a little insight or just slap me in the head and tuen me in the right direction if this is all wrong?

  2. DonQ

    AAC Fanatic!

    May 6, 2009
    'and then going there using ORG 2000H"

    ORG doesn't "go there". It only moves the location where the assembler is placing the code you write after the 'ORG' directive.

    Look at the difference between an "assembler directive" and a "Z80 instruction". Then look at the Z80 instruction "JP" and "JR".

    You also need to learn how to use labels (another assembler directive that will make your life easier, along with anyone who will ever have to use your code).

    After that, you might want to look at "LDIR".
  3. AldoLinklot

    Thread Starter New Member

    May 6, 2009
    Ok, it appears LDIR would just be used to actually copy the instructions to 2000H if I setup DE HL and BC correctly something like this

    Code ( (Unknown Language)):
    1. Start:    LD BC,02H
    2.           ADD A,B
    3.           ADD A,C
    4.           LD  HL,(0003H)
    5.           LD  DE,(2000H)
    6.           LDIR
    if thats correct, it just replaces my 4 previous LD instructions.
    I still have the same problem. Changing my ORG 2000H to JP 2000H gets me to 2000H but once there, how do I make the instruction stored there(in this case 80 for ADD) actually execute.

    Code ( (Unknown Language)):
    1.           ORG 1800H
    3. Start:                     LD BC,02H
    4.                            ADD A,B
    5.                            ADD A,C
    6. Setup locations:           LD  HL,(1803H)
    7.                            LD  DE,(2000H)
    8.                            LDIR
    9.                            JP  2000H
    11. Execute at 2000H:    Now that Im here, how do I make the
    12.                      80 stored here actually execute like
    13.                      an instruction.
    15. Return to original:        JP 180EH
    16.                            LD  A,00H
    17.                            LD  (2000H),A
    18.                            LD  (2001H),A
    19. End:                       HALT
    Last edited: May 6, 2009
  4. AldoLinklot

    Thread Starter New Member

    May 6, 2009
    Thanks for the help DonQ Ive figured it out.

    LDIR would probably be a more efficient way to setup the instructions at 2000H on but I dont have time to set it up that way.

    The key is to setup HEX code for the add instructions and the JP instruction going back to the original spot

    IE the memory map starting at 2000H would read something like this

    80 81 C3 18 23

    Once that is setup correctly, using a JP 2000H to get there will automatically run through that code first doing the two adds and then at 2002-2004 the JP back to the original area would execute.

    Again, thanks for the help DonQ. Sometime we just need that little spark.
  5. DonQ

    AAC Fanatic!

    May 6, 2009
    The JP instruction loads the PC (program counter) with the address of the next instruction to execute. Just doing the jump executes the instruction at that address, same as if it was the next instruction in line. Then when you're done, JP back to the original code.

    (Note: you could also do this as a CALL nn, RETURN.)

    Here is more what I was meaning by use labels. When you do this, you don't have to count the number of bytes of the instructions. You let the assembler do it for you.
    Code ( (Unknown Language)):
    2.             ORG   1800H
    3. START:      
    4.             LD    BC,02H
    5. COPYSTART:  
    6.             ADD   A,B
    7.             ADD   A,C
    8. COPYEND:
    9.             LD    DE,COPYSTART          ; COPY FROM
    10.             LD    HL,START2             ; COPY TO
    11.             LD    BC,COPYEND-COPYSTART  ; FOR THIS # OF BYTES
    12.             LDIR                        ; MOVE THE CODE
    13.             JP    START2                ; GO THERE AND EXECUTE IT
    14. RESTART:
    15.             LD    A,NOP ; SOME ASSEMBLERS LET YOU DO THIS
    16.                         ; OTHERWISE, LD A,00H (Z80 NOP IS 00H)
    17.             LD    (START2),A
    18.             LD    DE,START2
    19.             LD    HL,START2+1
    21.             LDIR
    22.             HALT  ; HALT HERE, or whatever
    25.             ORG   2000H
    26. START2:    
    28.                                       ; DEFINES AN UNITIALIZED SPACE OF THE STATED SIZE
    31. END:
    This is overkill, but supposed you wanted to add some more instructions? With this version, you just put the instructions between the CopyStart and CopyEnd labels and everything else is handled for you.

    Didn't syntax check this, working from memory, but this should give you the idea.
  6. AldoLinklot

    Thread Starter New Member

    May 6, 2009
    I understand the use of the labels, they do make life easier.

    Problem is I had to follow the format as originally posted, just replacing NOP's with other instructions.

    About the jump, I was under the impression that JP address would just bring you to a address and then look for the next instruction the programmer actually entered. After your previous post I researched it a little more and realized it worked the way you said in the last post.

    With that knowledge I was able to do what I needed to do.

    I hesitate to post my finished code because I noticed there is another student from what appears to be the same class on this forum asking a question about the other problem, the PIC one.

    I wouldnt want the same code to come in on someone elses paper and I get accused of collaboration.

    But again, your second to last post pointed me in the right direction and I was able to get through from there.

    Thank You
  7. tr1p1ea

    New Member

    Jul 29, 2009
    You could use 16-bit load/store and call, maybe something like this:

    Code ( (Unknown Language)):
    1. ORG 1800H
    3. ADD A,B
    4. ADD A,C
    5. LD HL,(1800H)        ; load 2 bytes starting at 1800H into HL (2 instructions)
    6. LD (2000H),HL        ; store 2 bytes in HL to 2000H
    7. LD A,C9H             ; opcode for RET
    8. LD (2002H),A         ; store to 2002H after previous 2 instructions
    9. CALL 2000H           ; call 2000H, will execute instructions and return
    10. LD HL,0000H          ; load H and L with opcode for NOP
    11. LD (2000H),HL        ; store to 2000H
    12. LD A,00H             ; load A with opcode for NOP
    13. LD (2002H),A         ; store to 2002H (clear RET)
    14. HALT