Quantcast

Results 1 to 13 of 13

Thread: Begginer OpCode and assembler question

  1. #1
    The Curly Bard Wildside Expert CurlyPaul's Avatar
    Join Date
    Oct 2009
    Posts
    151
    Rep Power
    11

    Default Begginer OpCode and assembler question

    So I've started playing around with some assembler for the MD for the first time, I a life long programmer but never been fully immersed in Assembler before.

    I floundered around with a few different tutorials before settling on the one from the Tanglewood guy at https://blog.bigevilcorporation.co.u...tting-started/ as it seems the most complete and has some good explanations.

    Only issue is that some of the opcodes the guy uses don't seem to work correctly for me, for example DBRA doesn't work as expected it just loops around forever, and the accompaning source files for the blog are no longer available. I have the same assembler (outputs "SN 68k version 2.53" to the log file same as shown in the blog) so I would assume it's something to do with the contents of my make file:

    Code:
    68k /o op+ /o os+ /o ow+ /o oz+ /o osq+ /o omq+ /o oaq+ /p /o ae- source.asm, output.bin>error.log
    Which I got from the demo at https://mode5.net/Tutorials.html. Would anyone mind helping me out with all those switches please?

    The mode5 tutorial also includes an empy file at line 1 called Ramdat.asm. Everything still works without it though, so can I just remove it?

  2. #2
    WCPO Agent Mad Moham's Avatar
    Join Date
    Dec 2014
    Posts
    843
    Rep Power
    22

    Default

    I don't want to put words in his mouth, but I recall Matt Philips saying that he didn't write that as a tutorial and there are some mistakes in there so be careful if that's how you plan on learning asm.

  3. #3
    Hedgehog-in-Training Hedgehog-in-TrainingRoad Rasher
    Join Date
    Dec 2019
    Posts
    266
    Rep Power
    9

    Default

    Quote Originally Posted by CurlyPaul View Post
    for example DBRA doesn't work as expected it just loops around forever
    Can you post an example snippet of where this isn't working for you? This is a pretty straight forward instruction; decrement and branch if not condition. Are you sure you're using the same register in DBRA as the one that is loaded before the loop? Are you modifying said register in the loop, maybe? What does the debugger show for the register value in the loop that appears infinite? If you're just getting into assembly, a debugger is must.. because you haven't developed 'assembly brain' yet haha.

  4. #4
    The Curly Bard Wildside Expert CurlyPaul's Avatar
    Join Date
    Oct 2009
    Posts
    151
    Rep Power
    11

    Default

    Quote Originally Posted by Mad Moham View Post
    I don't want to put words in his mouth, but I recall Matt Philips saying that he didn't write that as a tutorial and there are some mistakes in there so be careful if that's how you plan on learning asm.
    I did pick up on that, that he was writing this as a newcomer's journey rather than the teachings of master, which is kind of why I liked it but yeah it had occured to me not everything will fully correct.

    In fact, now that I re-read my code with fresh eyes this morning, I can see I do have some DBRAs in there that appear to be working, so my initial thoughts are incorrect.


    Quote Originally Posted by turboxray View Post
    Can you post an example snippet of where this isn't working for you? This is a pretty straight forward instruction; decrement and branch if not condition. Are you sure you're using the same register in DBRA as the one that is loaded before the loop? Are you modifying said register in the loop, maybe? What does the debugger show for the register value in the loop that appears infinite? If you're just getting into assembly, a debugger is must.. because you haven't developed 'assembly brain' yet haha.
    Code:
    clear_ram:
            move.l #0x00000000, d0     ; Place a 0 into d0, ready to copy to each longword of RAM
            move.l #0x00000000, a0     ; Starting from address 0x0, clearing backwards
            move.l #0x00003FFF, d1     ; Clearing 64k's worth of longwords (minus 1, for the loop to be correct)
            @Clear:
                move.l d0, -(a0)           ; Decrement the address by 1 longword, before moving the zero from d0 to it
                dbra d1, @Clear            ; Decrement d0, repeat until depleted
            rts
    Screen shot of the registers as seen in Gens, and yes indeed I need to understand the debugger more I was hoping to get Hello World working first but I think I'll dive into that tonight. Those bad/unknown messages look like they need sorting out, and is it possible to step through the code in any emulator? or do I need a rare and expensive dev kit for that?

    Untitled.jpg

  5. #5
    Comrade as in friend. Master of Shinobi ComradeOj's Avatar
    Join Date
    Dec 2012
    Location
    New Mexico, USA
    Age
    25
    Posts
    1,414
    Rep Power
    61

    Default

    Hey, I'm the creator of those tutorials. (the mode5 ones, not the tanglewood ones) I hope they were able to help a little bit, even though they didn't really go very far. If you want to PM me, I would be more than happy to help you out with Genesis assembly. Also, the ramdat.asm file is what I use to define variables and other RAM locations. I don't think my tutorials made any use of it, and it's really just a leftover.

    You can learn more about the switches by running the 68k.exe compiler program without any parameters. This is what it prints out:

    To be totally honest, I just used the same switches that were used from a sonic the hedgehog disassembly. As far as I could tell, these switches were all optimizations. It always compiled code fine for me, so I never really put any more thought in to it.

    Code:
    SN 68k version 2.53
    
    Copyright (c) 1988-1997 S.N. Systems Software Limited,  all rights reserved
    
    Edited by Nemesis on 1/11/2007. Increased the maximum path length, and added
    support for filenames and paths which contain spaces. Spaces are also supported
    with the /j option, however include paths specified with /j must now always be
    terminated by an asterisk. Eg, use asm68k /j "c:\include\*".
    
    USAGE : asm68k /options source,object,symbol,listing,temporary file
    
    Options :
    	/c		enable listing of conditioned out lines
    	/d		debug mode - do not run
    	/e symb=value{;symb=value}	equate symbol(s)
    	/g		write non-global symbols to linker object file
    	/i		display information window
    	/j path		specify include file search path
    	/k		allow use of ifeq, etc.
    	/l		produce linkable output file
    	/m		expand macros in listing file
    ----MORE/o opts		set assembler options/optimisations
    	/p		produce pure binary output file
    	/ps		produce binary file in s-record format
    	/q		run quietly
    	/w		write equates to symbol/linker file
    	/x		treat undefined symbols as XREFs
    	/z		include line number info in linker file
    	/zd		generate source level debug info
    Assembler options (first of +/- specified is default) :
    	ae+/-		automatic even on dc/dcb/ds/rs .w/l
    	an-/+		allow alternate number format
    	c-/+		case sensitivity
    	d-/+		descope local labels on equ, set, etc.
    	e+/-		print lines containing errors
    	l-/+		use '.' as leading character for local labels
    	l<char>	make <char> the local label character (not + or -)
    	p<processor>	allow opcodes for specified processor
    	r-/+		make external word offsets section relative
    	s-/+		treat equated symbols as labels
    	w+/-		print warnings
    	ws-/+		allow white space in operands
    	v-/+		write local labels to symbol file
    	x-/+		assume xrefs are in the section they are declared in
    Processor types supported :
    	68000 (default)
    	68010
    	68020
    Optimisations (first of +/- specified is default) :
    	op-/+		pc relative optimisation
    	os-/+		short branch optimisation
    	ow-/+		absolute word addressing optimisation
    	oz-/+		zero offset optimisation
    	oaq-/+	addq optimisation
    	osq-/+	subq optimisation
    	omq-/+	moveq optimisation
    Modded consoles:
    Master System (v7040) with s-video & direct AV out
    Model 1 with 10mhz overclock & halt switches
    Model 1 with 10mhz 68010
    Model 2 VA2.3 with unfiltered Mega Amp, & s-video
    Model 3 VA1 with compatibility fixes & s-video
    32X with s-video
    Visit my web site at www.mode5.net
    Or my collection of homebrew Genesis games, programs, and music on SEGA-16!

  6. #6
    The Curly Bard Wildside Expert CurlyPaul's Avatar
    Join Date
    Oct 2009
    Posts
    151
    Rep Power
    11

    Default

    Quote Originally Posted by ComradeOj View Post
    Hey, I'm the creator of those tutorials. (the mode5 ones, not the tanglewood ones) I hope they were able to help a little bit, even though they didn't really go very far. If you want to PM me, I would be more than happy to help you out with Genesis assembly. Also, the ramdat.asm file is what I use to define variables and other RAM locations. I don't think my tutorials made any use of it, and it's really just a leftover.
    [/CODE]
    They certainly did! Was the first thing I found that got me up and running and comparing your init methods to the tanglewood ones has been a useful learning tool It's your clear ram routine I'm using, I was just curious what was wrong with the other one as it reads like it should work to me.

    Appreciate the offer of help dude, and everyone above. I knew this would be the place to find the best help

  7. #7
    Comrade as in friend. Master of Shinobi ComradeOj's Avatar
    Join Date
    Dec 2012
    Location
    New Mexico, USA
    Age
    25
    Posts
    1,414
    Rep Power
    61

    Default

    Quote Originally Posted by CurlyPaul View Post
    They certainly did! Was the first thing I found that got me up and running and comparing your init methods to the tanglewood ones has been a useful learning tool It's your clear ram routine I'm using, I was just curious what was wrong with the other one as it reads like it should work to me.

    Appreciate the offer of help dude, and everyone above. I knew this would be the place to find the best help
    Glad it was able to help you! I like to think that SEGA-16 is a pretty good place for tech help, and it usually is.

    Not sure what's wrong with that clear RAM routine. Try changing the DBRA instruction to DBF and see if it works. Are you using any interrupts (vblank/hblank)? It could be that you`re re-using that loop counter register for some other purpose and it's throwing everything off. Also, you have to call that subroutine with either a bsr or jsr instruction. Conditional branches like bge, bne, blt, etc don't push the program counter on to the stack, so you can't use an rts instruction to your code.

    You also mentioned a hello world program. I'm assuming you're talking about the one from big evil corporation. I also made one too, if it helps you at all. The spacing is kind of messed up on a lot of editors though. https://mode5.net/download/hello%20world%20example.zip

    Also, look in to an emulator called "exodus". It's my go-to debug emulator. I prefer the first 1.0 release though, since the UI is kind of screwy on the later ones.
    Modded consoles:
    Master System (v7040) with s-video & direct AV out
    Model 1 with 10mhz overclock & halt switches
    Model 1 with 10mhz 68010
    Model 2 VA2.3 with unfiltered Mega Amp, & s-video
    Model 3 VA1 with compatibility fixes & s-video
    32X with s-video
    Visit my web site at www.mode5.net
    Or my collection of homebrew Genesis games, programs, and music on SEGA-16!

  8. #8
    The Curly Bard Wildside Expert CurlyPaul's Avatar
    Join Date
    Oct 2009
    Posts
    151
    Rep Power
    11

    Default

    It does work when I use DBF?? There hblank and vblank interupts defined yes, but they just rts right back out. I'm still a little suspicious of it as it deliberately wipes the entire memory, where as the comments in one of your examples indicates we should leave some of the upper address' alone. What's held in there that we should leave alone?

    And also, the include ramdat statement, being on the first line of the file doesn't it displace all the copyright messages and entry point headers?

    Thanks for the working example as well, that's most useful

  9. #9
    Hedgehog-in-Training Hedgehog-in-TrainingRoad Rasher
    Join Date
    Dec 2019
    Posts
    266
    Rep Power
    9

    Default

    Quote Originally Posted by CurlyPaul View Post
    I did pick up on that, that he was writing this as a newcomer's journey rather than the teachings of master, which is kind of why I liked it but yeah it had occured to me not everything will fully correct.

    In fact, now that I re-read my code with fresh eyes this morning, I can see I do have some DBRAs in there that appear to be working, so my initial thoughts are incorrect.




    Code:
    clear_ram:
            move.l #0x00000000, d0     ; Place a 0 into d0, ready to copy to each longword of RAM
            move.l #0x00000000, a0     ; Starting from address 0x0, clearing backwards
            move.l #0x00003FFF, d1     ; Clearing 64k's worth of longwords (minus 1, for the loop to be correct)
            @Clear:
                move.l d0, -(a0)           ; Decrement the address by 1 longword, before moving the zero from d0 to it
                dbra d1, @Clear            ; Decrement d0, repeat until depleted
            rts
    Screen shot of the registers as seen in Gens, and yes indeed I need to understand the debugger more I was hoping to get Hello World working first but I think I'll dive into that tonight. Those bad/unknown messages look like they need sorting out, and is it possible to step through the code in any emulator? or do I need a rare and expensive dev kit for that?

    Untitled.jpg
    You're looking at the starting address $000000. That's the rom header that the system looks at. That's data, not your opcodes. You need to find out where you code lives; look at the generated symbol table, or step through the code until you find it. Or just simply scroll through the debugger window and set a break point on what looks to be the same code.

    Also, how do you know that the loop isn't working if you haven't set a break point and stepped through the code??? It's possible that is working just fine. Also, what Comrade said.. your int routine could be trashing the same reg (doubtful if it's a simple example, but turn off the interrupts anyway to see). Everything looks fine at first glance; it's not an alignment issue, the address is wrap around from the top into ram but that's fine, the amount decrementing doesn't look like it should write beyond ram and setting an exception (but you can shorten the $3fff to $200 for peace of mind). Be careful, some debuggers/emulators don't throw an exception for memory alignment issues (don't use an old emulator/debugger). But anyway, you could solve this in a matter of minutes with a debugger.

  10. #10
    Comrade as in friend. Master of Shinobi ComradeOj's Avatar
    Join Date
    Dec 2012
    Location
    New Mexico, USA
    Age
    25
    Posts
    1,414
    Rep Power
    61

    Default

    Quote Originally Posted by CurlyPaul View Post
    It does work when I use DBF?? There hblank and vblank interupts defined yes, but they just rts right back out. I'm still a little suspicious of it as it deliberately wipes the entire memory, where as the comments in one of your examples indicates we should leave some of the upper address' alone. What's held in there that we should leave alone?

    And also, the include ramdat statement, being on the first line of the file doesn't it displace all the copyright messages and entry point headers?

    Thanks for the working example as well, that's most useful
    The ramdat file will just contain lines like:

    lives = $ff0000
    playerposition = $ff0002
    decompress_space = $ff1000
    ...etc etc

    It doesn't actually compile in to code, and it only used to label different parts of RAM to make coding easier. Because it doesn't actually turn in to code, it doesn't displace anything.

    Are you using rts for your interrupts? You want to be using rte instead, since interrupts are considered a special exception instead of a normal subroutine.

    The very top end of memory is where the CPU stack is normally at. If you erase 100% of memory, then it will also clear the return address that got pushed on to the stack when you called the RAM clear subroutine. If this happens, the CPU's program counter will jump to $000000 when it hits the rts instruction at the end of the subroutine and the program will crash.
    Modded consoles:
    Master System (v7040) with s-video & direct AV out
    Model 1 with 10mhz overclock & halt switches
    Model 1 with 10mhz 68010
    Model 2 VA2.3 with unfiltered Mega Amp, & s-video
    Model 3 VA1 with compatibility fixes & s-video
    32X with s-video
    Visit my web site at www.mode5.net
    Or my collection of homebrew Genesis games, programs, and music on SEGA-16!

  11. #11
    Hedgehog-in-Training Hedgehog-in-TrainingRoad Rasher
    Join Date
    Dec 2019
    Posts
    266
    Rep Power
    9

    Default

    Quote Originally Posted by ComradeOj View Post
    The ramdat file will just contain lines like:

    lives = $ff0000
    playerposition = $ff0002
    decompress_space = $ff1000
    ...etc etc

    It doesn't actually compile in to code, and it only used to label different parts of RAM to make coding easier. Because it doesn't actually turn in to code, it doesn't displace anything.

    Are you using rts for your interrupts? You want to be using rte instead, since interrupts are considered a special exception instead of a normal subroutine.

    The very top end of memory is where the CPU stack is normally at. If you erase 100% of memory, then it will also clear the return address that got pushed on to the stack when you called the RAM clear subroutine. If this happens, the CPU's program counter will jump to $000000 when it hits the rts instruction at the end of the subroutine and the program will crash.
    Looking at this example code; it's doing a pre-decrement before it writes to 0. So the top 4 bytes of ram isn't erased. So he's off by one, but if he's clearing $4000 bytes, then his loop might be writing to $FFFEFFFC on the last write (DBRA stops at -1 and not 0) and that could be an exception or /DTACK isn't acknowledged so it's just waiting. I don't remember DBF, honestly, but if it stops at 0 instead of -1, then that's why it works and DBRA doesn't.

  12. #12
    The Curly Bard Wildside Expert CurlyPaul's Avatar
    Join Date
    Oct 2009
    Posts
    151
    Rep Power
    11

    Default

    Yeah, I did try putting other numbers into d0 and it did reflect in what I can see in the registers. Lots of really useful stuff here guys and lots to get stuck into, thank you

  13. #13
    Level 1 Blast Processor Road Rasher
    Join Date
    Sep 2012
    Location
    England
    Posts
    341
    Rep Power
    30

    Default

    Quote Originally Posted by CurlyPaul View Post
    Code:
    clear_ram:
            move.l #0x00000000, d0     ; Place a 0 into d0, ready to copy to each longword of RAM
            move.l #0x00000000, a0     ; Starting from address 0x0, clearing backwards
            move.l #0x00003FFF, d1     ; Clearing 64k's worth of longwords (minus 1, for the loop to be correct)
            @Clear:
                move.l d0, -(a0)           ; Decrement the address by 1 longword, before moving the zero from d0 to it
                dbra d1, @Clear            ; Decrement d0, repeat until depleted
            rts
    Untitled.jpg
    You cant clear RAM like that inside a subroutine, because you are also clearing the stack, which holds the return address for you to call RTS. That RTS will jump back to 0x0000.

    You'd need to either clear up to the current stack address, or put that code back into the top level routine.

    Those blog posts are very very old and very very incorrect, I've been writing new samples here: https://github.com/BigEvilCorporation/megadrive_samples

    EDIT: ah this was already mentioned, I can't read

    If you want a better debugger for beginners, give this a try: https://github.com/BigEvilCorporation/MDStudio

    It's a Mega Drive IDE based on ASM68K.EXE and DGen, with source level debugging, Visual Studio-like debugging shortcuts, symbol search, and a few more things. It's very experimental and there's a lot wrong with it, but just the fact you can do source debugging is massively useful. I've got a few improvements ready to commit, I'll try and do a new release when I get a chance.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •