Wow, I guess 68K development isn't overly popular around these parts... Still, I need help and I was hoping I could find it, so I am posting here (as well as other sites). Here is the story:

-I have a TI-89 Titanium
-I am horrible with computer (read: I don't like installing software because it is too complicated for me)
-I have been wanting to program in assembly on my TI-89 for a few years, now
-I have a TI-84+ and SE
-I am familiar with z80 ASM and its syntax
-Yesterday I finally found an easy to install assembler for my 89-- an oncalc one called as().
-I have a tough time with mnemonics-- I notoriously learned Z80 through playing with hexadecimal and after learning z80 assembly, it took almost a year to understand mnemonics.


So pretty much, if anybody could explain instruction in a z80-ish or TI-BASIC way, that would be great! I am not familiar whatsoever with languages such as C, so I will not get C code or references Sad

I looked at a "Hello World" example, and there is a lot more there than with a Z80 and almost none of it I understand. I have tried tutorials, but it is not clicking for me yet. Here are the instructions that I am currently interested in:

movem.l d4/a5,-(a7)
I am assuming this writes using d4 and a5 to the address pointed to by a7? Does the negative mean it decrements A7 ? I saw somewhere that A7 was a stack register
move.l HeapAllocPtr*4(a5),a0
I have no clue what this syntax means. I checked out the hex and that helped me realise that it is like a 2 byte instruction followed by 0288h (which is HeapAlloc*4). But what does it mean to be right before (a5) ?
jsr (a0)
Is this some kind of relative jump?
pea.l 3840
Does the .l mean it is a "long" operation? The hex has a 32-bit value equal to 3840. But what does pea mean and what does it do?
tst.l d4
I cannot even begin... "tst" looks like test, so is this some way to check if an event has happened with d4?
beq.s nomem
I haven't a clue, but since nomem is a label, does this jump
move.l #3840,(a7)
Does this push an immediate value to the stack?
pea.l LCD_MEM
I've not a clue... LCD_MEM seems to have a value of 4C00h, but this seems to be different from the last pea.l instruction (the hex is 4079h as opposed to 4879h, so this tells me that it is just a flag difference or a slight difference in operation from my experience with z80 hex)

lea.l 12(a7),a7
I don't get the syntax :/
pea.l Hello_World(pc)
again, I is slightly different from the first pea.l (the hex is 487A versus 4879). This tells me that it is the same style if it were like z80
clr.l -(a7)
I am not sure what clr.l is. It looks like clear?
My 68k is pretty rusty, but I think this is accurate..

Code:
movem.l       d4/a5,-(a7)
Move Multiple (longwords). Copy d4 and a5 to the stack with predecrement. In z80 terms, you're pushing the values of d4 and d5 onto the stack.

Code:
move.l         HeapAllocPtr*4(a5),a0
Load the (longword) value at (HeapAllocPtr*4) + a5 into a0. The parens for indexing is a bit weird, but not uncommon syntax.

Code:
jsr              (a0)
Jump to Subroutine. Push the PC (move.l pc,-(a7) more or less) and jump to the address stored in a0.

Code:
pea.l           3840
Push Effective Address (longword). Same as something like the following, but doesn't clobber any registers:
Code:
 move.w #3840, d0
 move.l d0,-(a7)


Code:
tst.l            d4
Yes, test longword. Sets the integer condition codes, in this case it's checking if the result from the earlier jsr instruction is 0.

Code:
beq.s          nomem
Branch if equal (short). Equal being if the zero flag is set, so jump to nomem if d4 is zero.

Code:
move.l        #3840,(a7)
This actually seems useless, since 3840 is already the top value on the stack..

Code:
pea.l          LCD_MEM
Push the address of LCD_MEM onto the stack. The display is memory-mapped, so writing to the chunk of memory at LCD_MEM displays things on the screen.

Code:
lea.l          12(a7),a7

Add 12 to a7. Since that's the stack pointer, we're returning it past the last three longwords that got pushed. What this really says is set a7 to the value of (a7 + 12).

Code:
pea.l          Hello_World(pc)
Push the address of the Hello_World label (specified relative the the current PC) onto the stack.

Code:
clr.l            -(a7)
Yes, clear longword. Same effect as
Code:
pea.l #0
might have, since clr zeroes out the destination operand, and we're using the stack pointer in predecrement mode (eg, pushing something).

Putting it together:

Code:
; Push d4 and a5.  I believe these are the arguments to HeapAllocPtr
 movem.l d4/a5,-(a7)
; Get the address of the system routine HeapAllocPtr
 move.l HeapAllocPtr*4(a5),a0
; Call HeapAllocPtr
 jsr (a0)
; Push 3840 for some reason (presumably later code uses it)
 pea.l 3840
; Jump to nomem if d4 is 0 (memory allocation failed)
 tst.l d4
 beq.s nomem
; Throw some new values on the stack (HeapAllocPointer probably did some stuff to it and cleaned up its arguments)?
 move.l #3840,(a7)
 pea.l LCD_MEM
; Move a7 up 12 bytes and push the address of Hello_World.
 lea.l 12(a7),a7
 pea.l Hello_World(pc)
; Write 0 to top-of-stack
 clr.l -(a7)

This code doesn't make a lot of sense out of context, but there you go.. I suspect it's a rather poor learning example, since it seems to be optimized rather heavily. ..oh.
On reflection, it looks like these are just some parts that you ripped out because they weren't obvious. Meh, most of my conclusions still hold. The parts that I couldn't make sense of are those that you seem to have taken out of context.
Really though, you're better off programming the 68k in C, since it's got a rich instruction set for high-level languages (<3 link).

The 68k reference manual is a good resource otherwise.
68K asm? Most people ignore that in favor for 68K C.

I actually don't know of anyone that programs 68k asm. o.o Everyone just says to go with C.
Thanks, so far! I am currently looking into some stuff over on Technoplaza and it is very helpful!

Also, I think I will like assembly versus C, even if all it means is longer time to code, but more optimised code. I doubt I will get more optimised than the C compilers for a while, but I hope to eventually get there Smile
tifreak8x wrote:
68K asm? Most people ignore that in favor for 68K C.

I actually don't know of anyone that programs 68k asm. o.o Everyone just says to go with C.
There's a very good reason for that. The C compilers for the Motorola 68000 are very mature, and produce tight, fast code. Hand-writing ASM just isn't worth it when your code is far more maintainable and easy-to-manage in C, and your compiler will do just as good a job or better at producing the corresponding ASM as you might do. Smile
The C ABI can be quite ghastly at times though compared to what one might write by hand, but more often than not, the code that you write won't be very time sensitive. If I were you, I would just inline some ASM when doing routines that can't sacrifice a single clock cycle.
Like Kerm said, the slight run time expense of using C is worth the ability to quickly and easily express high level concepts (at least in this situation, C is a relatively high level language).

To this day, there are several concepts that I use in C all the time, yet I have no clue how to implement them in z80. If there was a decent C compiler for the z80, I would use it.
Hmm, well maybe it is time to learn C as well... I still want to learn M68K first so that I can better appreciate C, but I do know that it will be advantageous for me to learn C.
The TechnoPlaza tutorials are quite good, indeed Smile

"as" is certainly the old as in cc/as... and it was known for mild instability. The GTC FlashApp + ASM IDE might have a more featureful and more stable ASM support.

Several notes:
* people usually write "sp" instead of "a7";
* pea.l 3840.w needs to be before jsr (a0);
* the return value of HeapAllocPtr (TI's name for malloc) is in a0 (because it's a pointer type, it would be d0 if it were an integer type), not in d4. To test whether malloc returned NULL, "move.l a0,d0" (move to data register, which updates the Z flag and other flags - the other way round, move.l d0,a0 would not update the flags) and then beq.s nomem;
* "movem.l d4/a5,-(a7)" needs to be paired up with "movem.l (a7)+,d4/a5" when the stack pointer is at the correct location, near the end. And the code snippet you posted assumes that a5 was pre-loaded with the address of the jump table (ROM_CALL table), which can be done through "movea.l 0xC8.w,a5".

If your assembler doesn't support the 3840.w and 0xC8.w notations, don't use the ".w" - but your assembler may then needlessly waste 2 bytes for each invocation Smile
"0xC8.w" is requesting the assembler to use the 16-bit xxx.w addressing mode, which the processor will sign-extend to 32 bits: 0x0-0x7FFF are unchanged (so 3840.w and 0xC8.w do the right thing), 0x8000-0xFFFF are 0xFFFFnnnn so they're not usable as pointer or unsigned values.
Hmm, thank you much! I am still trying to read through all of the AMS call things, too, and I have made one simple program, but that was in C (it draws an inverted line that has endpoints bouncing around the screen at different rates).

It is definitely nice to know that loading an address register to a data register updates the flags. That seems like it could be useful. Can I also do move d0,d0 and accomplish the same thing except with d0?
Quote:
Can I also do move d0,d0 and accomplish the same thing except with d0?

* for testing the 16 LSB of the 32-bit data register, tst.w dn, and.w dn,dn and or.w dn,dn (this one being a common idiom in x86 ASM, but seldom used in 68000 ASM) will all do the job with 2 bytes and 4 processor clocks;
* for testing all 32 bits of a data register, I _think_ that move.l dn,dn updates the flags, indeed, and it would be faster than tst.l dn, and.l dn,dn and or.l dn.dn. But you should double-check Smile


For clearing the 16 LSB of a 32-bit data register, clr.w d0, sub.w d0,d0 and eor.w d0,d0 (common x86 idiom, infrequent in 68000 ASM) do the job in 2 bytes and 4 processor clocks.
For clearing all 32 bits of a data register, the fastest way is moveq #0, d0 (2 bytes, 4 processor clocks). Specifying the size for moveq is optional, since it's always .l. "moveq.w" is accepted by the old A68k assembler, but is incorrect.
Wow, thanks much! I need to find all the clock cycle info and the hex associated with the mnemonics... Do you know where I could find this?
* the mnemonics, their detailed description and hex codes can be found in the Mototola 68000 Programmer's Reference Manual (I have that under the "M68000PRM.pdf" name here);
* the clock cycles information is in the 68000 User Manual ("68000UM.pdf" here) Smile

GoldenCrystal from yAronet made a quick reference card for the 68000 opcodes, http://bit.ly/M68kOpcodes .
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement