![]() |
Forum Index : Microcontroller and PC projects : Shift Left or Right in MMBasic
![]() ![]() |
|||||
Author | Message | ||||
twofingers Guru ![]() Joined: 02/06/2014 Location: GermanyPosts: 1535 |
That's not completly wrong! I think we should have a TBS-MMBasic standard lib for something like that. This includes mathematical (log10), string (trim$, InStr$) and bit operation (shift, reverse) functions. Today we may have all this somewhere/somehow but no one knows exactly where to look for. And one day ... Geoff will integrate the entire library in MMBasic v10! ![]() Or?? Michael causality ≠correlation ≠coincidence |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
Hi I'm more than happy to write some functions and act as the library editor if people want to contribute functions. An editor is needed to ensure naming consistency, eliminate namespace collisions, packaging and distribution of the library, documentation standards and so on. If this idea has legs then we probably need to establish the guidelines, eg naming conventions, documentation headers, error handling/reporting. In the meantime here's some useful little functions. ' 'Returns 1 if X is Odd, 0 otherwise ' FUNCTION Odd(X) Odd=X AND &H1 END FUNCTION ' 'Returns 1 if X is even, O otherwise ' FUNCTION Even(X) Even=(X AND &H1) XOR &H1 END FUNCTION ' 'Shift X Left by N bits ' FUNCTION ShiftL(X,N) ShiftL=X*(2^N) END FUNCTION ' 'Shift X Right by N Bits ' FUNCTION ShiftR(X,N) ShiftR=X\(2^N) END FUNCTION ' 'Remove leading Spaces from string ' FUNCTION LTrim$(X$) LOCAL I,Z$ Length LEN(X$) 'Make copy of caller's string so that we don't damage it Z$=X$ FOR I=1 TO LEN(Z$) 'Find first NON-Space character IF MID$(Z$,I,1)<>" " THEN Z$=MID$(Z$,I) EXIT FOR ENDIF NEXT I LTrim$=Z$ END FUNCTION ' 'Remove trailing Spaces from string ' FUNCTION RTrim$(X$) LOCAL I,Z$ Length LEN(X$) 'Make copy of caller's string so that we don't damage it Z$=X$ FOR I=LEN(Z$)-1 TO 1 STEP -1 'Find first NON-Space character IF MID$(Z$,I,1)<>" " THEN Z$=MID$(Z$,1,I) EXIT FOR ENDIF NEXT I RTrim$=Z$ END FUNCTION ' 'Remove spaces from LHS and RHS of string ' FUNCTION Trim$(X$) LOCAL Y$ length LEN(X$) 'MMBasic doesn't like Trim$=RTrim$(LTrim$(X$)) Y$=LTrim$(X$) Trim$=RTrim$(Y$) END FUNCTION Peter The only Konstant is Change |
||||
plasma Guru ![]() Joined: 08/04/2012 Location: GermanyPosts: 437 |
why not Shl / Shr / Rol / Ror / Asr / Asl |
||||
WhiteWizzard Guru ![]() Joined: 05/04/2013 Location: United KingdomPosts: 2927 |
Because I believe that would mean using six command indexes from a very limited remaining quantity! I have 'guessed' the first four; but what are the last two? ![]() The thing I like about BASIC is that PRINT means print, LIST means list, RUN means run, INPUT means input, SETPIN means set pin, but Asr means what exactly ???? Shouldn't need to think about it IMHO ![]() |
||||
plasma Guru ![]() Joined: 08/04/2012 Location: GermanyPosts: 437 |
http://en.m.wikipedia.org/wiki/Arithmetic_shift |
||||
WhiteWizzard Guru ![]() Joined: 05/04/2013 Location: United KingdomPosts: 2927 |
I've never come across that one before - interesting (but personally struggling to find a use for it). Just noticed at the bottom of the BSF webpage (for page navigation) there is a '<<' sign for the previous page - guess that means 'Shift Left Previous' ![]() I do prefer << and >> instead of 'shortened' named functions such as SHL and SHR. But the number of command indexes remaining for Geoff to utilise has to be considered. So I'm still for SHIFT with a parameter to indicate direction; closely followed by << and >>. Lets see what he decides as there is quite a bit of debate here with the overall majority favouring << and >>. << WW >> ![]() |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
ASR/ASL Argh !!! Where's the carry in MMBasic. ASL/ASR are really vital in doing multiple precision arithmetic in assembler, mod and \ are what I use in MMBasic to do multiple precision arithmetic Next someone will ask for a DAA instruction followed by a an SBCA, ADCA - Motorola fans may recognise these ![]() Peter The only Konstant is Change |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
' 'Returns 1 if X is Odd, 0 otherwise ' FUNCTION Odd(X) Odd=X AND &H1 END FUNCTION ' 'Returns 1 if X is even, O otherwise ' FUNCTION Even(X) Even=(X AND &H1) XOR &H1 END FUNCTION ' 'Shift X Left by N bits ' FUNCTION ShiftL(X,N) ShiftL=X*(2^N) END FUNCTION ' 'Shift X Right by N Bits ' FUNCTION ShiftR(X,N) ShiftR=X\(2^N) END FUNCTION ' 'Remove leading Spaces from string ' FUNCTION LTrim$(X$) LOCAL I,Z$ Length LEN(X$) 'Make copy of caller's string so that we don't damage it Z$=X$ FOR I=1 TO LEN(Z$) 'Find first NON-Space character IF MID$(Z$,I,1)<>" " THEN Z$=MID$(Z$,I) EXIT FOR ENDIF NEXT I LTrim$=Z$ END FUNCTION ' 'Remove trailing Spaces from string ' FUNCTION RTrim$(X$) LOCAL I,Z$ Length LEN(X$) 'Make copy of caller's string so that we don't damage it Z$=X$ FOR I=LEN(Z$)-1 TO 1 STEP -1 'Find first NON-Space character IF MID$(Z$,I,1)<>" " THEN Z$=MID$(Z$,1,I) EXIT FOR ENDIF NEXT I RTrim$=Z$ END FUNCTION ' 'Remove spaces from LHS and RHS of string ' FUNCTION Trim$(X$) LOCAL Y$ length LEN(X$) 'MMBasic doesn't like Trim$=RTrim$(LTrim$(X$)) Y$=LTrim$(X$) Trim$=RTrim$(Y$) END FUNCTION The only Konstant is Change |
||||
plasma Guru ![]() Joined: 08/04/2012 Location: GermanyPosts: 437 |
haha substract with borrow from A . ![]() |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
@WW I think that ASR and ASL are equivalent to 'Have to assume 16 bit integer Function ASR(X, Carry) Carry=X AND &H1 ASR=(X \ 2) AND &HFFFF End Function 'Have to assume 16 bit integer Function ASL(X,Carry) Carry=X AND &H8000 ASL=(X * 2) AND &HFFFF End Function Peter The only Konstant is Change |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
plasma Ah, Ah so you must have played with 680X then !! The '09 was a really clean orthogonal architecture, the last of the 8 bit CPUs. Peter The only Konstant is Change |
||||
twofingers Guru ![]() Joined: 02/06/2014 Location: GermanyPosts: 1535 |
@Peter, An editor is needed to ensure naming consistency, eliminate namespace collisions, packaging and distribution of the library, documentation standards and so on.
If this idea has legs then we probably need to establish the guidelines, eg naming conventions, documentation headers, error handling/reporting. Yes! It can also be done in a team. I will collect and rethink my functions and open then a new thread for that. Hopefully you are this editor (I use and like your LCD library) ![]() @WW It's a matter of self documentation. That's clearly important but not realizable completely in any case. Some functions are very sophisticated (matematical, logic) and some have to have short names, because of the execution speed. In my opinion, programming is always a compromise: Readability, speed and programers laziness. ![]() Regards Michael edit: @Peter looks good I will check it later. For me it is important, once and for all to have a library that I can rely on. Good work! causality ≠correlation ≠coincidence |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
I suppose we could do ![]() ![]() Function SHIFT(Type, Operand, Number of Bits) where Type could be 0=>> 1=<< 2=ASR 3=ASL 4=ROR 5=ROL but what a handful and of very limited use, really only <</SHIFTL >>/SHIFTR are of use in a high-level language IMHO. Peter The only Konstant is Change |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
By Documentation I mean the stuff which describes the Function, eg Purpose, Args in/out, side affects (hopefully none), global vars used (hopefully none), performance characteristics, eg duration of a call to the function at 40MHz, Example usage etc, all of this stuff would be contained in comment lines which get stripped off by MMEdit before download to the target uMite and so would impose NO memory or performance impact but which are vital for usability and maintainability. With libraries there is always a comprise to be made between robustness, performance, and flexibility. Generally most libraries have several versions. One built for robustness, eg with lots of error/limit/size checking, one built for performance, eg NO/minimal error/limit/size checks, one built for flexibility, eg lots of optional arguments into calls but which often results in larger memory/cpu footprint. So for example in the few little functions I published earlier, the more robust versions of the TRIM functions would check that the length of the string on entry was at least 1, and the more flexible version of the TRIM functions would have an optional argument specifying which character to throw away rather than just space. BTW, I use the #define capability of MCPP to reduce long variable/sub/function names to single/dual characters at download time to the uMIte. That way I can keep nice friendly descriptive symbols in my source, but at runtime they all get converted transparently, here's an example from my PIC32 MMBasic based programmer 'Shorten symbols #define Args A LOCAL Args(8) 'Shorten symbols #define H16Out X #define L16Out Y LOCAL H16Out,L16Out 'Shorten the Symbols at runtime #define XferFastData S1 #define XferData32 S2 #define XferData F3 #define SendCommand S4 #define XferInstruction S5 #define Initialise S6 #define SetMode S7 #define ExitProgMode S8 #define Clock S9 #define Send8Bits SA OK ? Peter The only Konstant is Change |
||||
twofingers Guru ![]() Joined: 02/06/2014 Location: GermanyPosts: 1535 |
but that's C! Will the compiler not anyway eliminate all names and replace with his own labels? Michael causality ≠correlation ≠coincidence |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
@twofingers MMBasic is NOT compiled. MCPP does the #define's on the source before download to the uMite, so MMBasic sees the result of the #defines, in this case much shorter variable/sub/function names. AFAIK, MMBasic doesn't really tokenize each line as it is loaded in - I could be wrong there, (I haven't spent any time trying to peek into Memory to find out - Geoff can of course clarify). If my assumption is correct then the MMBasic interpreter has to 'read' and parse each line as it executes the line, so the shorter the line the quicker is the read. If also subs/functions are hashed and held in a separate table then the hashing time will be less for shorter names, finally shorter names reduce the memory impact - it must be for all these reasons and more that Hugh Buckle developed his Crunch program. The other big thing about #defines is that I can get real constants in MMBasic which occupy no memory. Without #define, one has to write stuff like Dim PGD PGD=5 Setpin PGD, DOUT with #define #define PGD 5 Setpin PGD, DOUT which will result in Setpin 5,DOUT in the downloaded source The key difference here is that without #define, PGD is an MMBasic variable occupying memory, and it is actually slower in execution compared to using the constant 5 itself.# BTW, if MMBasic lines were parsed and tokenized as they were loaded, all numeric values would be converted into their equivalent internal MMBasic representation so that at runtime these values could be operated upon without any conversion time - really important in for/next/do/loop situations. Also if MMBasic lines were parsed/tokenized as they were loaded, syntax errors (even for unreached lines) would be flagged before execution, rather than is the case now where syntax errors are only flagged at execution time, finally if MMBasic lines were parsed/tokenized at load time, variables/subs/functions could be assigned in memory and references to those variables/subs/functions replaced with their actual addresses leading to faster execution. Oh, I forget, if MMBasic lines were parsed/tokenized, then one would see very standard line layout as one sees in VB for example, eg operators with exactly one space before and after, all MMBasic reserved names would have standard casing etc. I'm sure Geoff is fully aware of all of these and more techniques besides and may well have implemented some of them already in MMBasic. 73 Peter The only Konstant is Change |
||||
Goeytex Regular Member ![]() Joined: 12/05/2014 Location: United StatesPosts: 74 |
I prefer the << >> format. |
||||
twofingers Guru ![]() Joined: 02/06/2014 Location: GermanyPosts: 1535 |
@Peter U are of course right! I was confused. It's late in europa. On the first glance it looks like C. What's this MCPP? It's it for µMites only? About speed and loops: Yesterday I checked the execution time of loops. do/loops are much slower as for/next. I had not expected. In my little Game of Life project (for Maximites) I tried all this optimization options. Michael causality ≠correlation ≠coincidence |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
No, MCPP is a C preprocessor, just google for MCPP. To make best use, you should be using MMEdit and then from the advanced menu use "auto run external on load". You can get MCPP and all the other required stuff to go with it, eg .BAT file to interface to MMEdit, from http://www.g8jcf.dyndns.org/mmbasic/index.html Peter The only Konstant is Change |
||||
vegipete![]() Guru ![]() Joined: 29/01/2013 Location: CanadaPosts: 1122 |
As someone who uses C, I'm quite happy with << and >>. However, SHIFT or SHIFTL/SHIFTR would work just as easily. (Or maybe BSHIFT to mean bit shift, ensuring the 'f' is not lost.) But I do like the idea of a signed shift amount. I could see cases of not knowing ahead of time which direction the shift will be. SHIFT var,num is much cleaner than IF num < 0 THEN SHIFTR var, -num ELSE SHIFTL var, num Since (for me at least) the main point in bit shifting is to get the bits that fall out the end, another useful version would be outbit = SHIFT(var, num) where outbit gets the value shifted out the end. ex: var = 0b01001110 num = 3 SHIFT(var,num) gives 0b010 _AND_ changes var to 0b01110000 Thus, a ROLL function becomes: outbit = SHIFT(var, num) var = var OR outbit 'Note this is a bitwise OR Another interesting thought is longer bit structures. For example, a graphics LCD screen (128x64 pixels) needs 1024 bytes for a frame buffer. This could be stored in a string (or string array.) If that string could then be bitwise shifted appropriately, the entire frame buffer could be scrolled left, right up or down with a single SHIFT command. (The shift amount could be quite large, even 128, to scroll a frame buffer up or down one line, depending on screen pixel layout.) ============ Note, I assume a positive shift value is to the left in order to behave like exponents. Visit Vegipete's *Mite Library for cool programs. |
||||
![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |