Addressing Modes: Z80 Assembly Language for the ZX Spectrum Tutorial, Episode 2

Поделиться
HTML-код
  • Опубликовано: 7 янв 2025

Комментарии • 77

  • @JanVandenBergh1974
    @JanVandenBergh1974 3 года назад +12

    This reminds me of when I had a ZX81 and tried to write assembly code for it. I did not have an assembler, so had to assemble the code by hand.
    Good times!

    • @flaviusnita6008
      @flaviusnita6008 3 года назад +4

      What a glorious times. I spent half of my life programming by hand! I knew all (all!) Z80 instructions by heart!

    • @ian_b
      @ian_b 3 года назад +2

      Same!

    • @valuemastery
      @valuemastery Месяц назад +1

      When I was 12 years old, we had a (6502 powered) Commodore PET at school. Not only did I not have an assembler, I also had no book about assembly programming. So I peeked into the ROM of the machine with the Hex monitor, and studied it until I was able to write my own code. Took me 5 hours to figure out the first machine operation. Printed out the hex codes in smallest font and folded it down to wear it in the wristband of my watch, to be able to carry it with me all the time. I remember the machine code to this day.
      Later, I bought a book.

  • @NonTwinBrothers
    @NonTwinBrothers Год назад +1

    There can't be a more awesome feeling than knowing there's 10 more of these. Truly an awesome resource for someone learning, like myself :D

  • @hkmmos659
    @hkmmos659 8 месяцев назад +1

    Did try assembler when I was 15 years old, and build some pretty cool stuff, ie. a program that doubled the number of characters on the screen with smaller font, which I then used with a spreadsheet program I built in basic... Insane ... I would not be able to do this today.

  • @PebblesChan
    @PebblesChan 3 года назад +7

    A programming hint for using the IX and IY index registers with tables that have more than 127 bytes is to use an offset label to the table's datum. Doing this makes allows you to reference the table with a 8 bit (relative) offset.

  • @vintageshed965
    @vintageshed965 3 года назад +6

    Your series is tempting me to repair my old Didaktik M (48k spectrum compatible)and try the coding myself.

    •  3 года назад +1

      You can already try coding on Zesarux, CSpect and other emulators. If you want you can even use XZbaremulator on Raspberry Pi.

    • @vintageshed965
      @vintageshed965 3 года назад +1

      @ I could, but that would rob me of the authentic experience of the crappy mechanical keyboard the M is famous for. 3 of 5 times it either write nothing or multiple characters at once, which you can't emulate 😁
      Just joking, I'm definitely going to try them.

    • @andrewdunbar828
      @andrewdunbar828 3 года назад

      I'd watch if you repair it in RUclips videos! I'm yet to see any repair videos on Speccy clones.

    •  3 года назад

      @@vintageshed965 Au contraire. ZXbaremulater is a bare metal emulator, i.e. it doesn't run on an operating system (you don't need to install Linux to use it). It's the most faithful option before resorting to FPGA. And you can use a mechanical keyboard on it connecting the flat strips to the GPIO pins on the RPi with the help of some diodes. It works. I did it to an old Brazilian TK90X computer. Runs as smooth as a 40y/o computer should.

    •  3 года назад +1

      @@andrewdunbar828 it was not a repair: I just let the TK90X's motherboard unplugged and connected the keyboard terminals to the Pi with the help of the diodes. Pros: perfect, no-lag 48k/128k running on bare metal connected to an HDMI monitor with modern creature comforts but using the rubbery 40-key keyboard. Cons: not the real Z80A and no way to connect a Light Pen/cartridge. But still better than a broken computer getting dust on a shelf.

  • @ped7g
    @ped7g 3 года назад +3

    Nice video. I'm usually tempted to add a bit here and there under similar videos, but nothing to add here.
    One minor technical detail about sjasmplus - that SAVESNA does provide fake sysvars, but the interrupt are disabled. So your last RET return to working basic prompt, but it has disabled interrupt, so it doesn't read keys. You can add `EI` before last RET to see it working. But also I would still recommend to not return anywhere from asm-tutorial-examples, the `JR $` infinite loop is the safest way to limit example code from further actions. Returning back to BASIC is trivial when you don't touch any parts of system (simple RET is enough often), but if you would pedantically try to list all preconditions how to "not kill ZX BASIC" during running your asm code, it's actually quite lengthy and convoluted topic, easily filling whole video or two.

  • @gregorymccoy6797
    @gregorymccoy6797 2 года назад

    Nice. I know assembly for the pic. This was a good intro to z80. I am building my own single board computer for fun and this will be very helpful. Thanks for all the work I know you put into this.

  • @mybricology7388
    @mybricology7388 Год назад

    At 18:44 even if it's only for an exercice, you'de better add a "DI" before the "IM1" instruction, much more safer. Then "EI" after "IM1"
    If you were in the position of writting a new BIOS ROM, "DI" is a good choice for the very first instruction.

  • @pawelartymowicz1617
    @pawelartymowicz1617 2 года назад

    ; thanks for the great series!
    As a student, I was lecturing on Basic programming of the ZX in the early 80s, I seem to remember that I was even paid for this. All that in Poland, behind the Iron Curtain. When I first came to the U.S. for a summer program at Space Telescope Sci. Inst for the finishing undergrads, I was good in science & programming (incl. on PDP11), and so was asked to apply for their graduate program, which promptly accepted me.

    • @nemis123
      @nemis123 2 года назад

      nice🙂I am learning this as absolutely new to me. It's tempting to use C compiler but I just want to feel the 80s nerd vibe!

  • @PebblesChan
    @PebblesChan 3 года назад +5

    When a Z80 encounters a RST 38 (0xFF) instruction usually from unpopulated memory region, it'll execute it and if the contents of 0038 is 0xFF (RST 38) it'll continue filling all of the RAM with 0x39, 0x00's. Think of it as the blue screen of death for a Z80.

  • @PebblesChan
    @PebblesChan 3 года назад +2

    In addition to the 64K memory address space, the Z80 also has 64K (i.e. 65536) I/O port addresses but in many cases only 256 of these are used. e.g. Instructions like IN A,(C) will read from I/O port BC. The same is applicable for other I/O instructions that use (C) references. The microbee uses a hybrid of I/O addresses being 8 bits for 256 port addresses with some additional output ports using input port addresses. e.g. LD BC,#(0x01

  • @idea1407
    @idea1407 3 года назад +1

    Thank you for the very very detailed lesson. A lot to digest here.

  • @MartinSteed
    @MartinSteed 3 года назад +3

    Your memory chart at 1:15 - that is quite some compression fitting 16kB into 0xFF58 - 0xFFFF :)

    • @slithymatt
      @slithymatt  3 года назад

      Oops! Copy and paste error there. Good catch! I'll fix that in the repo

    • @JohnBlackburn1975
      @JohnBlackburn1975 3 года назад

      @@slithymatt Yes, I noticed that too. The UDGs only occupy 21 x 8 = 168 bytes. Great tutorial BTW!

  • @braveitor
    @braveitor 2 года назад

    Nice video and very well explained. These are quite hard concepts to a standar programmer, so thanks for these videos. :)

  • @PebblesChan
    @PebblesChan 3 года назад +8

    You can make the index addressing modes more flexible by using self modifying code. To do this you get your code to alter the displacement byte in an instruction to your desired value. e.g. You can change an IX + 0 reference into a IX + 1 reference.

  • @owenjnelson-fb9mg
    @owenjnelson-fb9mg 2 месяца назад

    My assembler doesn't recognise ld a,(ix) so I've gone for sjasm but I couldn't get anything working for ages... I copied your code (which looked word for word exact) and it compiled ok, seems its just very fussy about the spacing! Up and running now though, so all good, looking forward to working through this, this is very good stuff, glad to see I still remember a lot of it aswell but this is going back a fair bit for me :)

  • @mmmbug
    @mmmbug 4 месяца назад

    You teach beautifully.

  • @HansBezemer
    @HansBezemer 3 года назад +1

    Again, a lovely trip down to memory lane! I even encountered some stuff I'd forgotten. It was also nice to see the index registers again. I once wrote a bubble sort using self-modifying code to "change" the index - ooh, I was a bad boy back then!
    A little remark - although you were perfectly on spot where the difference between JR and JP opcodes are concerned, you forgot to mention the MAIN reason to use JR over JP (IMHO). It's not "space", but making relocatable code! I interfaced a lot of stuff with Forth back then and since you can't predict where it ends up, relocatable code was a MUST.
    And yeah, I loved RET Z, RET NZ and RET C (if I remember correctly) back then. Still, when using Forth I use a ?EXIT (which is about equivalent to RET NZ) every now and then. That may seem like a big no-no (no multiple exit points), but in Forth routines tend to be a handful of lines, so you don't lose track that easily. It allows for the tail call optimizer to kick in. ;-) (May be an idea when you get to an optimization lesson).
    I love to see the next episode - keep up the wonderful work!

    • @slithymatt
      @slithymatt  3 года назад

      I'll definitely be getting into more of that stuff in my episode on flow control, going deep into all the conditional instructions.

  • @PebblesChan
    @PebblesChan 3 года назад +1

    NMI on a DRAM model microbee is not used as NMI but as an alternative to /RESET to ensure that its DRAM contents remain intact.

  •  Год назад

    Very good! I am watching now!!!

  • @StarsManny
    @StarsManny 3 года назад

    Fantastic tutorial, thank you!

  • @TheAgent4125
    @TheAgent4125 3 года назад

    Woo! I've been waiting for this! :)

  • @DAVIDGREGORYKERR
    @DAVIDGREGORYKERR 3 года назад

    Guys if you want to follow along get a MEMOTECH MTX512+FDX512+HDX512+RAM Expansion module+any printer with a Centronics printer port will work.,
    To assemble some machine code do for example ASSEM 10 or what ever line number you want to finish assembly type RETURN RETURN .
    To Debug do PANEL and go to &h4000
    To execute scripts do for example PLOD 10
    To write scripts do NODDY
    To execute machine code do GOTO 10 or RANDOM USR(16384)
    also if you have the full system you can even run CPM/80 not sure if CPM/80 has a compiler but is a lot of fun.
    is Clear screen RST $38
    if an Assembly session has finished successfully and if you list the program you will see the ...
    10 CODE
    Machine code
    which should finish with the instruction RET
    references to the various labels and values that you have used
    RETURN

  • @britlion
    @britlion 2 года назад

    FF58 to FFFF is 168 bytes. Not 16KB as per your memory map at the start.

  • @ZxSpectrumplus
    @ZxSpectrumplus Год назад

    Hi, i am beginner with this. Can i clarify something. I assume that you cannot load a value from memory address to another memory address? Everything must be done via registers as intermediate storage medium, is this correct? Also, i can't seems to ld a harcoded value directly into a memory address. Are the following examples invalid instructions?
    ld ($1234), $05
    ld ($1234), ($9ABC)

    • @slithymatt
      @slithymatt  Год назад

      The only way you can load directly from memory to memory is using an address register: HL, IX or IY. So to copy from $1234 to $ABCD can be done like this:
      LD HL,$ABCD
      LD (HL),$1234

  • @retronexusio
    @retronexusio 3 года назад +1

    love it

  • @markrayne5382
    @markrayne5382 3 года назад

    Hey Matt awesome series! I have a question, I just finished reading Cold by Charles Petzold where he details the intel 8080 micro processor, I then wanted to find a good emulator for the 8080 but was told that it would be a better move to go with Z80, Z80 supports most if not all of the 8080 opcodes and functionality as far as I know, Are you using Windows or Linux to run the emulation software?
    Thanks

    • @slithymatt
      @slithymatt  3 года назад

      Z80 is 100% compatible with 8080, but has support for a bunch of additional instructions that are really handy, and eventually was used far more than the original 8080. I am using Linux, and there a bunch of emulators for different Z80 systems, especially the ZX Spectrum, MSX and Sega Master System.

    • @PebblesChan
      @PebblesChan 3 года назад +2

      The Z80 extremely close but is technically not 100% 8080 compatible. 8080 contains a bug with its BCD subtraction instructions with the DAA instruction which Z80 has fixed. Often this bug is used to identify a system's CPU. Because of this 8080 bug, its DAA instruction should only be used directly after an addition instruction such as ADD, ADI, ACI.

  • @andrewdunbar828
    @andrewdunbar828 3 года назад +1

    I learned asm on the Z80 then some years later learned asm on the 680x0. Big endian seemed perfectly logical and natural. When the 486 came out little endian seemed illogical and confusing. I had utterly forgotten that Z80 was little endian!

    • @lawrencemanning
      @lawrencemanning 3 года назад +1

      Yup. A selling point of the Z80 was 8080 compatibility, hence little endian. And yeah, big endian is far more logical.

    • @PebblesChan
      @PebblesChan 3 года назад +2

      Little endian is handy for accessing the same memory location either as a BYTE or WORD value using the same label. e.g. ld a,(label) and ld hl,(label).

    • @andrewdunbar828
      @andrewdunbar828 3 года назад

      @@PebblesChan Yeah that's the usual justification but in practice I never missed that in the days I was programming Amigas, the only time I was actually a professional programmer. But I miss bigendian stuff while programming little-endian systems to this day. There's a toy project I'm doing right now that would be so much more straightforward on bigendian because I could access the same memory as bytes or words or 64 bit units including bit shifting.
      I know that I used to do pixel movement of graphics on the Speccy using shifts and the carry bit for sprites multiple characters wide though. So it must've made sense to me once (-:

  • @PebblesChan
    @PebblesChan 3 года назад +1

    Using some undocumented instructions you can access the IY and IX registers as 8 bit registers. e.g. IYL, IYH, IXL & IXH.
    In some eyes, the index registers are relatively useless thus the Nintendo Gameboy CPU replaces these op codes with more useful instructions.

    • @slithymatt
      @slithymatt  3 года назад

      Are those really undocumented? I guess I never checked the original Zilog docs and assembler to see if they are called out, but other assemblers and documents support them. It's not like you need to use DB directives to enter machine code

    • @andyleighton3616
      @andyleighton3616 3 года назад +1

      @@slithymatt Most of the undocumented instructions have been known about, documented by third parties, and used for 40 years - so I wouldn't worry too much. Some of them (the autocopy ones) are wild though (and aren't supported by some assemblers) - for example SLA reg, (IX+nn) - do a SLA (IX+nn) and store the result in (8 bit) reg as well. Unfortunately (HL) isn't allowed for a destination - as it maps to the documented SLA (IX+nn)

  • @thomasasteven5432
    @thomasasteven5432 3 года назад

    May I know, where is the Episode 1?
    Thank you 🙏

    • @slithymatt
      @slithymatt  3 года назад

      The whole playlist is back on my channel page

  • @abibi5515
    @abibi5515 3 года назад

    yeees assembler!

  • @kilianhekhuis
    @kilianhekhuis 3 года назад +1

    "16-bit increments do take longer, as they may require doing a carry to the higher byte" - not quite, as the Z80 only has a 4-bit ALU, so even 8-bit increments need a carry-over in between partial ALU results. That said, _any_ addition needs carry propagation, as the very first two bits added could already produce a carry. So the only reason a 16-bit increment/addition takes longer, is just that it's twice as many bits to add. You need a 16-bit ALU to do 8- and 16-bit additions in the same time.

  • @kirill_bykov
    @kirill_bykov 3 года назад

    1:20 too much for UDG.

  • @bobns509
    @bobns509 3 года назад

    At 1min26sec... the FF58-FFFF is much less than 16Kb.

    • @slithymatt
      @slithymatt  3 года назад +1

      Already fixed the slides in the repo.

    • @bobns509
      @bobns509 3 года назад

      @@slithymatt Ah, ok. Sorry.

    • @slithymatt
      @slithymatt  3 года назад

      @@bobns509 no worries!

  • @MackTheBass
    @MackTheBass 3 года назад +3

    Since you are talking about a British machine, the Speccy - it's ZED 80 not ZEE 80 !

    • @slithymatt
      @slithymatt  3 года назад

      😒

    • @georgeprout42
      @georgeprout42 3 года назад +4

      Brit here as well. I'd compromise with Zee 80 as Zilog are American, as long as it is always Zed Ecks Spectrum.

    • @PebblesChan
      @PebblesChan 3 года назад +1

      In OZ, we called it the Z.A.T.

    • @PebblesChan
      @PebblesChan 3 года назад +2

      George Lucas from Star Wars called his 4 legged walker the Intel 8080 (AT-AT). He also used the Apple ][ reference of AA23.

    • @HelloSwiftful
      @HelloSwiftful 3 года назад +3

      Matt explained this in his previous video, since the Z80 is an American microprocessor, he calls it the ZEE 80, but when referring to the British machine, he compromises to ZED EX. The bigger picture is about the content, not about someones pronunciation.