Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Iambian

Pages: 1 ... 49 50 [51] 52
751
ASM / Assembly Coding Optimization
« on: June 12, 2007, 06:36:00 am »
QuoteBegin-calc84maniac+12 Jun, 2007, 10:32-->
QUOTE (calc84maniac @ 12 Jun, 2007, 10:32)
The Better CP HL,DE
compares hl to de, same flag outputs as 8-bit compare
c1-->
CODE
ec1or a
sbc hl,de
add hl,dec2
ec2  

 Are you sure that would work? Wouldn't the "ADD HL,DE" destroy the Z flag set by the SBC? If anything, shouldn't the the "OR A \ SBC HL,DE" and the "ADD HL,DE" be switched?

Or is it something I'm not getting?

752
Other Calculators / Wabbitspasm
« on: May 27, 2007, 05:22:00 pm »
You know, with all this talk about ti83plus.inc, I just want to remind or point out that I'm not using any include files.

So, what was the solution to the problem again? I couldn't decipher the post that had it well enough to figure out what to do. (yes. I'm a n00b. I need these things spelled out to me... )

753
ASM / Assembly Coding Optimization
« on: May 23, 2007, 04:01:00 am »
EX (SP),IY and the like *do* work, according to the "documentation". They're slow, so I wouldn't recommend using 'em unless you ran out of registers or something (which is very likely in high-intensity situations).

It's just that EX DE,HL lacks that same kind of modifier. And don't we wish EXX had that kind of modifier? :Ptongue.gif

But for some other assembly code optimizations...
( meh. I'm running out of things to say... )

To make use of the wonderful array of flags, you should make all loops that count decrement toward zero. In this way, you remove the needed CP instruction prior to the condition test and you cause the loop to run faster. If you're using register B for this purpose, then you should already be familiar with the DJNZ instruction. If you need something counting upward, however, you can use an extra register to keep track of the count. If you are running short on registers, you can do some CPL/NEG magic with the counter if the count upwards happens to be starting from 255 counting downward, or if the counting number happens to require that kind of value.

As with any ASM optimization, you ought to write your code first and then see if you can improve the code's form in any way. Whether it be taking advantage of a conveniently placed flag, condensing the code so it uses less registers, removing instances of "slow" instructions in favor of "faster" instructions, limiting the scope of what your code is doing to *exactly* what it should do... and making sure that if you make any changes to subroutines with its input, ensure that the input values of the calling routine are well-suited to handle the changes.

Sometimes, you will want to change input values to certain subroutines because the calling routine will usually have its input in a certain format. For example, if you needed a routine that would extract size bytes out of a program var right after a _chkfindsym, you'd take DE as the address of the program. If you're doing this multiple times, you're saving yourself a few bytes of having to do "EX DE,HL" each time you called _chkfindsym.

Experiment with these optimizations, but before you do any kind of optimization, please, for the love of all that is good, make sure that the program works prior to potentially breaking it. You'll thank yourself later.



754
Other Calculators / Wabbitspasm
« on: May 21, 2007, 03:39:00 pm »
Perhaps the problem might be the location in which some of the RAM equates are defined. SPASM gives many errors when the lines:
c1-->
CODE
ec1#define equ .equ
755
Other Calculators / Wabbitspasm
« on: May 16, 2007, 08:26:00 am »
Even though this isn't the forum to discuss such a thing, but SPASM doesn't work out well for me. The assembler crashes when I attempt to compile FISH7.asm (source included with this update to game "Fishy" on UTI). I'm still trying to sort out what I did wrong or if it's really a problem with SPASM.

For now, I'll just stick with TASM or something.

756
ASM / Assembly Coding Optimization
« on: April 30, 2007, 12:23:00 pm »
Oh. I thought that anyone with a decent knowledge of the Z80 instruction set would see the connection between any instruction that includes HL and turning it to IX or IY.

The only thing that is *not* self-explanitory is the lack of an EX DE,IY or EX DE,IX instruction, or any other exchanges that play around with HL. (believe me; I've tested the EX DE... thing)

And on a previous topic, the assembler would actually take JP (DE) or JP (A). TASM would complain about a missing label, tho. If you have either DE or A defined as a label, TASM would evaluate (DE) as the location of the label itself and not the stuff at the label, as the indirection might've indicated.

Perhaps this is a good way to obfuscate your code?

Of course, if you have the assembler invoked with the right flags, TASM would emit a warning.

757
Other Calculators / ASM program needed
« on: April 30, 2007, 06:07:00 am »
Whee! Posting in something whose problem has already been solved. I'm a genious, aren't I? :Ptongue.gif

But anyway, I think my fun, earlier project would work too, even if it seems a little bloated: http://www.unitedti.org/index.php?download=212

The ReadME should be helpful. The program has been tested for *some* semblance of reliability.

758
ASM / Assembly Coding Optimization
« on: April 30, 2007, 05:45:00 am »
JP (HL) works with JP (IX) and JP (IY) and not JP (DE) because of the way the Z80 instruction set works. Since there's an opcode for JP (HL), and the docs say that many instructions that work with HL can also work with IX and IY, that would seem self explanitory. A little study of the instruction set would reveal that any IY or IX instruction is simply the corresponding HL instruction with a prefix byte attached to tell the processor to treat the instruction using the index register instead of the original HL register. Because of the way the processor works, you also get these "undocumented" instructions that allow one to edit the LSB or the MSB of the index registers.

Is JR (A) even a valid instruction? I can't find it anywhere in the documentation, so I dun think that's supported by the Z80. Correct me if I'm wrong by showing me the corresponding opcode and what the binary turns out to be.

But, if one wanted to use SMC relating to a JR instruction and a jump table, one could try something like this, provided that the table is page-aligned (aligned to $xx00)
c1-->
CODE
ec1
 LD HL,$8000;assuming that the table is in the $800-$80FF space
 LD L,A
759
Introduce Yourself! / Joining in the Forums
« on: April 30, 2007, 05:25:00 am »
I'm wondering about something.

Where did the tradition about throwing nuts at newcomers come from? I'm not upset or peeved or anything about it, but I'm just a little curious. An appropriate link would be helpful.

760
Other Calculators / Some (Z80) Assembly Required
« on: April 19, 2007, 05:36:00 am »
I figured that this is the place to post such a topic.

http://iambianet.freewebpage.org/t/index.html

A long while ago, I started writing out these tutorials in a fashion of "how these topics come into mind." What I want is some advice on some of the things that could be changed. Proofreading is encouraged, but what I'm looking for is to determine if what I have is good and what else I need to add to further learning ASM on the TI-83 Plus SE.

Remember that "Some (Z80) Assembly Required" is a tutorial that should specifically address the learning of the programming language. Higher level stuff and possible optimizations will go in "More (Z80) Assembly Required". (Ideas for that are not discouraged. Post what you think you have in mind, just as long as you specify which tutorial you are referring to)

While reading, ask yourselves these questions and relply:
  • Is there enough information available to clearly define a topic? If not, what was confusing or what would need to be further discussed?
  • Are there topics that seem out of order? If so, could you suggest a better place? Perhaps on its own page? On a different page? A different paragraph?
  • Is the verbage or lexicon too difficult to understand? If you have to use a dictionary to read my tutorial, can you suggest simpler words that I could use or better phrases?
  • Are the examples used clear enough? Do I need to include more examples? Perhaps examples that relate to the TI-BASIC programming language?
  • Are there any sections that you believe are not necessary and can then either be cut out or reworded?
In addition, what other sections do you think I may need to address before asking the user to read "More (Z80) Assembler Required"? Should I actually go in-depth into the use of romcalls? The use of memory locations and common inputs? Do you find that I did not give a certain instruction enough attention? Did you find that I missed completely out on any very important instructions? Any topics that I might've missed?

Help is much appreciated in the construction of this tutorial.

761
ASM / Assembly Coding Optimization
« on: April 17, 2007, 04:28:00 am »
I actually got that trick off of some very old Z80 documentation. I just thought it curious.

In TASM, JR (condition),$+2 gives you the instruction after it, and JR (condition),$-1 gives you the instruction behind it. To make it continuously loop on itself (jump back to the beginning of the instruction), you'd do JR (condition),$+0, so it's natural to then believe that JR (condition),$+1 would give you one byte within the instruction.

Also, no errors will happen since TASM already recognizes the instruction to take a single byte argument. Believe me; I've tried a similar stunt before (though not as memory-efficient), especially if you read up on my unreadable Z80 source :)smile.gif

Also, to keep on topic:

For a speed optimization when working with a list of two-byte values, you can abuse the stack to quickly address these values. That is, set SP to the start of the list. Then you can repeatedly POP values off the table. The values are not destroyed, but only read. If you need to edit a value, say, for updating, you can just PUSH the value back in and use some instructions like INC SP (twice) to move the pointer back to where you were (although just POP-ing the value will save two clockcycles as opposed to using INC SP twice, except if you're trying to POP to an index register). Accessing values in this fashion will save you many clockcycles, especially compared to the standard "LD E,(HL) \ INC HL \ LD D,(HL) \ INC HL" sequence that eats up a hefty 26 clockcycles. Simply POP-ing the value will use up only ten clockcycles.

This is especially useful for bubble-sorting or perhaps grabbing the largest and smallest value on the table.

Remember to disable interrupts and to save SP prior to editing SP to read the table.
------------------
Another optimization trick is first of all, when you want to, say, stop the program to output an error message, you could, instead of loading in HL the address of the string, do the following instead:

c1-->
CODE
ec1CALL ErrorCode \ .db "ERROR1",0

ErrorCode:
 POP HL
;process string address now in HL
 JR ProgramEndc2
ec2
That works because when the CALL is made, the address in the stack will point to the string thereafter, since it would've been the next address to execute from then. The ErrorCode will have a jump to a place that will restore SP prior to exiting, so this will only work if you have code to restore the stack or something. If all your error messages are of a fixed size, you could save more space by cutting out that null-terminator and editing your text output routine to cope with a fixed-size.

For further optimization (in case you don't want to have code to jump over all that CALL and text), all ASCII alphabet characters are within the code block for loads. If you do not have any special characters, spaces, or numbers, you could actually have the call a conditional one and have your little Z80 run the text as if it was code. This is a dangerous practice, especially if you were going to change your text, but in this case, you'd be looking at an opcode table to determine which registers get destroyed in the various loads. The reason why I say that you cannot use the space character is because its opcode refers to a JR instruction. If you were especially savvy about the placement of your code, you could use this feature to your advantage.

Take care with the use of that optimization. It certainly isn't a speed optimization, but it most certainly is a size optimization, especially if you're CALLing on a condition that JR doesn't take (like M or P, for instance).

762
ASM / Assembly Coding Optimization
« on: April 16, 2007, 09:21:00 am »
It might also be worth it to mention, in case you're doing interrupts, that if you wanted to call the TI-OS's interrupt service routine (RST 38h) on a conditional jump, you could save some memory by using a trick of the Z80's instruction set.

Instead of, say, "CALL C,0038h" or "JP C,0038h", you could do "JR C,$FF". Conditions will vary, all of which will do the same thing.

This works because the "$FF" is an offset to make a relative jump one byte behind the already-executed instruction ( JR C,$+1). The part of the argument for JR, "$FF", is the opcode for RST 38h. In that sense, you're combining two instructions in one.

For what you'd use this for, I'd have no idea. Perhaps someone that wanted to call the interrupt service routine while the interrupts were off? Perhaps it might be a way to keep romcalls like _getCSC and _getKey working while the interrupts are gone.

763
Introduce Yourself! / Joining in the Forums
« on: April 16, 2007, 09:13:00 am »
Yeah. It *has* been that long, eh? That brings up old memories. Especially that time I first programmed FlashCrash. Heh. That was some time. Too bad I didn't stick around that long. I suppose it just took some time for the channel to make its way to DragonFire and then me sitting on that channel for... forever?

Thanks for welcoming me back, DJ Omnimaga :)smile.gif
I hope that my increased knowledge (since then) of Z80 ASM would help the community a bit better this time around.

764
TI Z80 / Zigel - Variable Storage
« on: April 12, 2007, 10:01:00 am »
QuoteBegin-Sonata+12 Apr, 2007, 11:58-->
QUOTE (Sonata @ 12 Apr, 2007, 11:58)
Definately. Great for BASIC RPGs when you need more memory. Could you store programs in there? Theoretically Id say yes...

You would be able to store programs, but not run them directly from "ExRAM".

Also, I was thinking of keeping track of the last address allocated in memory, so that allocation and deallocation would run faster by moving only what is needed. That is with the first TI-OS style memory allocation method. I still haven't developed anything for the second scheme, so that's still iffy.

I'm still planning this thing out on paper, since it wouldn't be the easiest thing to debug. Know that I can't use PTI to emulate this since PTI doesn't have support for the memory I'm trying to use, so development will naturally be slower than if I had an emulator that would work with this.

Any suggestions for commands that might be useful for interfacing with this move-only filesystem program? Maybe filesystem ideas?

So far, these are the specifics of the idea:

In addition to ROM pages 0 thru 7F (logically), there are RAM pages 0 thru 7, addressable as-is on port 5, or addressable through port 6 as $80 thru $87. Because of logic simplicity and the fact that the TI-OS on the TI-84 series uses RAM page 2 (for USB protocol), my program will use RAM pages 4 thru 7 and address it as if it was a single 64KB chunk. For that, I have a routine that transparently translates an address in a register (usually HL) to reflect a page and position in the $400-7FFF memory bank.

Programs are allocated from $0000 up to the end of the table, the table starts at $FFEF and grows downward. The spare 16 bytes beyond the table is reserved for filesystem variables, so they need not be stored in user RAM, and is then safe from other utilities that will use the standard saferam areas.

At the start of the table, each entry will be allocated 12 bytes per entry, irrespective of the variable's type. This is to ensure that traversing the table will happen as quickly and painlessly as possible, although a dynamic table size is certainly probable. Each entry is written backwards in memory, but each entry, shown forwards is as follows in offsets:
+0 : Data type
+1 : LSB of memory location
+2 : MSB of memory location
+3 : Reserved (possible use is a name size byte or something.
+4 to +11 : 8 bytes allocated to data's name. Null-padded.

Upon formatting this memory, one entry will be already on the table, and the variable created contains four bytes, two for its size and two for the data itself. It's name will be "!", and it serves the purpose of being a placeholder so there won't be a table with zero entries. Using the memory routines, an error will be generated if one attempts to delete "!" out of the memory.

At memory location $FFFE will reside a two-byte entry showing how much "Free RAM" there is. Although it could be calculated each time, I would like to keep it to verify the integrity of the filesystem.

At memory location $FFFC will contain a two-byte entry showing how many symbol table entries there are. This is used as a loop counter as the symbol table is traversed.

At memory location $FFFA will be the address of the last piece of data allocated in ExRAM. This value is used to calculate where the end of ExRAM is so that memory allocation and deallocation can run much more efficiently, so that they don't try to move unused memory (which would cause a massive slowdown if there was a large enough chunk between the end of the symbol table and the end of ExRAM).

More variables will be inserted into this "reserved" space as I see fit.

765
TI Z80 / Zigel - Variable Storage
« on: April 12, 2007, 04:58:00 am »
I had started this topic up on UnitedTI, but I wanted to see what the people here think of it. Between first mentioning it and posting it here, I came up with a name for the project, completely in the spirit of how I named Celtic.

This project is a filesystem program for the TI-83 Plus Silver Edition and all models of TI-84 Plus, capable of storing and retrieving variables of many kinds in 64KB of the available 96KB not in use by the OS. Information in this memory cannot be executed, but it can be swapped in and out so as to provide some alternative to archiving objects (which can wear down on Flash and cause frequent garbage collects).

Input and output will work in a fashion similar to Celtic, the commands being to move a said variable into "ExRAM", move a variable back into "User RAM", check the integrity of "ExRAM", one to determine the amount of "ExRAM" that is free, and one to format it.

Two different filesystems have been planned out for this program, so two different editions will be available nearing the end of developing this project.

The first one will operate like the TI-OS's RAM allocation and deallocation methods. Working with 64KB of RAM, the said operations can become slow, especially under the worst possible conditions where performing said functions can take upward to a full second.

The second one will work similar to FAT, allocating files a certain number of "chunks". That method will work lightning-fast, but a lot of memory will be wasted in the "slack" produced by allocating an entire sector to a small variable. For this, I plan to divide up the 64KB of RAM into 256 sectors, each 256 bytes in length.

Memory management interface is planned to work almost identical to the TI-OS's memory manager.

I do understand that applications will cause conflicts (Omnicalc, virtual calculator, RAM recovery) that could result in the data being destroyed. For that, I can only suggest that this project be used in RAM-intensive applications and programs where the user would not be able to interact with any conflicting applications during the use of program (i.e. a game). It will then become the programmer's responsibility to ensure that nothing important remains in the area of RAM at the end of the program.

Have you any thoughts regarding the project? Perhaps suggesting which edition I work on first? A better filesystem? Or do you think such a program would be, in general, useless? Maybe there's a command that you'd like to see in addition to those described?

Pages: 1 ... 49 50 [51] 52