![]() |
Forum Index : Microcontroller and PC projects : 8-bit unsigned integer?
Author | Message | ||||
homa![]() Guru ![]() Joined: 05/11/2021 Location: GermanyPosts: 471 |
Hello Geoff as the author of MMBasic, is there a reason why you didn't include an 8-bit unsigned integer? Especially for the old protocols and serial interface transfer and byte operations, etc. it would be helpful to have an 8-bit unsigned integer. I find this quite cumbersome with the shift operations and bit manipulations always the 64 bits to consider. Would it be conceivable for you that this data type exists in the future or it is introduced? Apart from that how is the memory consumption of 64-bit integer in an array if I use only the first 8-bit? Wouldn't memory consumption decrease by a factor of 4 with a short 8-bit? Or am I making a thinking error here? I would appreciate a brief explanation. I hope I was able to formulate my question understandably enough. Many greetings Matthias I found this online and in the PicoMite manual: https://mmbasic.com/overview.html MMBasic supports three data types; (double precision) floating point [ !], 64-bit (signed) integers [ %] and strings [ $]. These can be stored in variables and arrays and can be operated on using the normal BASIC syntax. Shift operators: x << y x >> y These operate in a special way. << means that the value returned will be the value of x shifted by y bits to the left while >> means the same only right shifted. They are integer functions and any bits shifted off are discarded. For a right shift any bits introduced are set to the value of the top bit (bit 63). For a left shift any bits introduced are set to zero. 64-bit Unsigned Integers MMBasic on the PicoMite supports 64-bit signed integers. This means that there are 63 bits for holding the number and one bit (the most significant bit) which is used to indicate the sign (positive or negative). However it is possible to use full 64-bit unsigned numbers as long as you do not do any arithmetic on the numbers. 64-bit unsigned numbers can be created using the &H, &O or &B prefixes to a number and these numbers can be stored in an integer variable. You then have a limited range of operations that you can perform on these. They are << (shift left), >> (shift right), AND (bitwise and), OR (bitwise or), XOR (bitwise exclusive or), INV (bitwise inversion), = (equal to) and <> (not equal to). Arithmetic operators such as division or addition may be confused by a 64-bit unsigned number and could return nonsense results. Note that shift right is a signed operation. This means that if the top bit is a one (a negative signed number) and you shift right then it will shift in ones to maintain the sign. By the way: The link to http://geoffg.net/Micromite.html leads to a 404, only changing it to http://geoffg.net/micromite.html with small m leads to the desired website! |
||||
Mark Regular Member ![]() Joined: 26/11/2022 Location: United StatesPosts: 85 |
At least on the PicoMite, the Str2Bin supports 8-bit unsigned ints. What are you trying to di? |
||||
stanleyella![]() Guru ![]() Joined: 25/06/2022 Location: United KingdomPosts: 2566 |
byte = 64 byte = byte + 1 =65 byte = byte + 255=63 |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
A new datatype is very unlikely to happen but there are lots of ways of working with bytes PEEK, MEMORY PACK/UNPACK STR2BIN/BIN2STR etc. |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
Whereas there is plenty of scope for diffent datatypes, the core code of MMBasic would likely require extensive reworking to accomodate them and the various type checks fr mismatches etc. From my PEEKings back in November; a variable entry in VARTABLE is 64 bytes long, integer values only occupy 8 of those bytes (yellow box). Floats occupy four bytes. A theoretical single byte datatype would possibly occupy one but the entry for the variable would still be 64 bytes long. No memory saving would be realised if the same scheme were followed. The following is far from complete and possibly inaccurate. One question remains: How do I tell where the end of the vartable is (i.e. how many variables have been definded?) ![]() Edited 2023-02-12 07:36 by CaptainBoing |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
I don't think you can on that particular implementation (Micromite?) as it doesn't look like it sanitises unused blocks. Even if it did the gaps created by local variables being deallocated or the use of ERASE would make it difficult. For the same reason you can't just add a variable with a distinctive name and look for it in the table. Internally the 'mites I'm familiar with maintain a variable counter but it isn't exposed to BASIC. EDIT: If you were desperate you could on startup POKE the table full of 0xFF (maybe just the type bytes), the maximum size of the table for this purpose could be looked up in the source code. You could then determine the maximum allocated index by scanning through the table looking for a 0xFF type byte, that would do it wouldn't it? Best wishes, Tom Edited 2023-02-12 10:00 by thwill MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
Sorry, yes, this is on MicroMites. As I understand it the method of handling variables on the Pi and CMM2 are different so that might not apply. I have gone through the source code (as well as I can - not a C programmer) and cannot see any way to detect the end of the table so a counter would explain that. I generally search 2048 bytes in 64 byte chunks which allows for 32 variables - probably about right for most tasks. I might add I am probably making a mountain out of a molehill here as I don't often piddle about with this stuff in my code. "Cleaning" the table is a nice idea but we are back to the "how far can I go?" problem - don't want to trample on stack or anything important... trial n error I guess. Edited 2023-02-12 21:33 by CaptainBoing |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7937 |
@homa No point really. Because of the way MMBasic works you save nothing by using 8-bit variables. They were handy on 8-bit processors, but there are penalties for having them on longer word length systems. You can simulate them if you need to, but your program will be slower. You can store up to 255 bytes in a string by using, for example: (where you are working with character position 100) POKE VAR a$, 100, &HF0 and retrieve it with x = PEEK(VAR a$, 100) Byte 0 of the string is its length. @Cap'n >>confused<< Why would anyone want to mess about with the variables table at all? POKE BYTE etc. let you mess with variables without the risk of screwing anything up. Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
TLDR; Code needs to know the name of a variable LV; I use dynamic arrays in quite a bit of my code - I needed a UBOUND() function. To do so I have to be able to find the variable in the table to retrieve its dimensions. By passing the name of the variable as a string, I can then search VARTABL and do the necessary. Yes there are other ways of handling dynamically DIMensioned arrays but none as compact as UBound("fred") ymmv "Why would anyone want more that 640K?" who knows what we get up to? If it were not intended to be used, it wouldn't be part of the language. The most I risk with PEEKing is processor exceptions during development. low risk Edited 2023-02-12 22:09 by CaptainBoing |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
So use a PicoMite ![]() This returns the upper limit of the array for the dimension requested. The dimension defaults to one if not specified. Specifying a dimension value of 0 will return the current value of OPTION BASE. Unused dimensions will return a value of zero. For example: DIM myarray(44,45) BOUND(myarray(),2) will return 45 |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
one day it might come to that but for now '170s provide all I need. I have UBound() and a few other enhancement functions I have written that make life comfortable. Speed is a consideration but if it becomes a "thing" I'd go for the H7 PiPico's are nice and cheap tho' ![]() Edited 2023-02-12 22:18 by CaptainBoing |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
Right, I've had another look and I think the MMBasic firmware for the MX170 (and possibly all of Geoff's ports other than MMBasic for DOS) use a dynamically growing variable table (unlike MMB4L and those of Peter's ports that I am familiar with). I think the C global "Memory.c#VarTableTop would need exposing to MMBasic for this strategy to work ... you may as well ask for Geoff to add BOUND to the MX170 firmware - if it can take it without cracking. From the source: /* all memory allocation (except for the heap) is made by m_alloc() memory layout used by MMBasic: |--------------------| <<< This is the end of the RAM allocated to MMBasic (defined as RAMEND) | | | MMBasic Heap | | (grows down) | | | |--------------------| <<< VarTableTop | Variable Table | | (grows up) | |--------------------| <<< vartbl This is the start of the RAM allocated to MMBasic (defined as RAMBASE) m_alloc(type, size) is called when the program is running and whenever the variable table needs to be expanded Separately calls are made to GetMemory() and FreeMemory() to allocate or free space on the heap (which grows downward towards the variable table). While the program is running an out of memory situation will occur when the space between the heap (growing downwards) and the variable table (growing up) reaches zero. Sorry that I can't be of more assistance, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
That is interesting info and corelates broadly to my understanding but your "C eye" has helped - thanks. It isn't problem so much and I feel I have already used up too much thread on it. I wouldn't ask for any additions to MMBasic for a couple of reasons: 1. it was announced a while back that MMBasic on 'Mites is considered in maintenance and only major bug fixes with no w/a would be considered 2. I am largely confined to an older version so wouldn't benefit from any updates. I use 5.0408 because after that version program changes flush any VAR SAVEd variables. I have one fairly big concern that stores config data in loads of "slave" modules. Admittedly I don't update the software that often (hardly ever) but the thought of re-configuring all of them as part of a program tweak is unpleasant. So I tend to stick with '0408, I have found it totally stable - never a problem in millions of hours of collective use. Edited 2023-02-12 22:50 by CaptainBoing |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3292 |
There a few reasons why 8 bit unsigned was not implemented. The first is... where do you stop? As well as 8 bit unsigned you could also wish for 1 bit, 8 bit signed, 16 bit signed and unsigned variables and so on. The second reason is that 64 bit variables work well and cover most requirements - their only real disadvantage is that arrays are larger but most implementations of MMBasic have plenty of free RAM, so that is generally not a big issue. Finally (and this is the most critical) MMBasic was designed for microcontrollers with limited flash memory. Providing more flash memory for the BASIC program was more important than adding marginal features like this. These days Peter has ported MMBasic to processors with far more flash but then, they also have more RAM, which reduces the need for features like smaller integers. Captain: Walking through the variable table is not really feasible for a BASIC program. As you noted, the overall size of the table is not exposed and anyway, this will dynamically change as variables are added and more RAM is allocated to the table (so zeroing the table will not work). As you might have discovered from the source, the variable table grows upwards while general RAM usage (arrays, buffers, etc) grows down. Unallocated RAM is in the middle. EDIT: Tom beat me to it! Geoff Edited 2023-02-12 22:47 by Geoffg Geoff Graham - http://geoffg.net |
||||
homa![]() Guru ![]() Joined: 05/11/2021 Location: GermanyPosts: 471 |
Thank you Geoff, thanks to all others. Good points. I will think about it a bit longer, but eventually ask again. Background to the question is that I deal a lot with protocols that are old and therefore mostly use only 8-bit values. DMX512, MIDI, EIB/KNX to name a few. In addition everything is based on 8-bit, 1-byte, ASCII. And the direct operations on these data types would be nice to explain it also to beginners (like my son) with "old" examples. With 64-bit signed you have to pay more attention. Special thanks also for this: Here I have always used string operators, very interesting! You never stop learning. The community here is great. Keep it up. Greetings Matthias |
||||
robert.rozee Guru ![]() Joined: 31/12/2012 Location: New ZealandPosts: 2442 |
BRILLIANT! just verified with the following: b=Asc("T") a$="cat in hat" Print a$, Peek(var a$,3) Poke var a$,3,b Print a$, Peek(var a$,3) End cat in hat 116 caT in hat 84 > have just been digging through the forum looking for threads where RAM usage was discussed back in 2019. much the same discussion then as now, and the same conclusion is that there was not much to be gained. on an MX170 there is enough RAM (approx 59k) for 150 or so 255-character strings, or nearly 700 simple float or integer variables. and using the above from Mixtel90, one can easily get byte-sized addressing into any variable, which pretty much covers 99% of the cases where a BYTE type could be wanted. HOWEVER, i also happened upon the following posting: https://www.thebackshed.com/forum/ViewTopic.php?TID=11271&PID=132913#132913 and gave the code a try on the current 5.05.05 MX170 firmware to see what has changed since 2019: i=0:z=1 Do j=Peek(progmem, i) If j>127 Then Print "[" Str$(J) "]"; Else If j<32 Then Print "<" Str$(J) ">"; Else Print Chr$(j); EndIf If j=0 Then Print :If z=0 Then End i=i+1:z=j Loop Saved 163 bytes <1>[159]i[198]0<0> [159]z[198]1<0> <1>[132]<0> <1><0> <1> [159]j[198][208]progmem, i)<0> <1> [156]j[197]127 [177]<0> <1> [166]"[" [164]J) "]";<0> <1> [134]j[196]32 [177]<0> <1> [166]"<" [164]J) ">";<0> <1> [136]<0> <1> [166][134]j);<0> <1> [142]<0> <1><0> <1> [156]j[198]0 [177] [166]<0> [156]z[198]0 [177] [144]<0> <1> [159]i[198]i[186]1<0> [159]z[198]j<0> <1><0> <1>[162]<0> <0> > geoff and peter: from the above, can one conclude that EVERY line starts with a 0x01, every line ends with a 0x00, and ':' as a statement separator is also encoded as 0x00? IF this is the case, could the 0x01 instead be replaced by any non-zero value less than 32 where it also encodes the whitespace (n-1 spaces) at the beginning of the line? ie: 0x01 something0x00 (4 leading spaces) would instead be encoded as 0x05something0x00? across a large basic program, that is correctly indented, this could save quite a few bytes of flash. for the above 163 byte program, there would be a saving of 26 bytes by my reckoning (equating to a 16% reduction in flash used). just an idea to kick around; i'm not suggesting that it would be worth doing in practice. cheers, rob :-) Edited 2023-02-13 03:10 by robert.rozee |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3292 |
Rob, a line can start with a line number or a label. That byte that you have identified is 1 for nothing, 2 for a line number and 3 for a label. However, there would be nothing stopping values above 3 representing the number of leading spaces (less 2). Also implementation should be easy. That sounds like a good idea, I will check with Peter to make sure that it does not mess him up and, if OK, have a look at implementing it in the next version. Geoff Geoff Graham - http://geoffg.net |
||||
robert.rozee Guru ![]() Joined: 31/12/2012 Location: New ZealandPosts: 2442 |
excellent! ![]() just ran the above bit of code with a couple of lines added to the end to demo labels and line numbers (61680 was used as the line number as it encodes as 240 for both high and low bytes): here: Rem this is a label 61680 Rem this is a line number which produced slightly different output to what you discuss: <1><0> <1><3><4>here [169]this is a label<0> <1><2>[240][240] [169]this is a line number<0> <0> but then this is the special version you built for me that accepts negative PWM values, so may be from different source to that used elsewhere: Micromite MKII MMBasic Ver 5.05.05 RR Copyright 2011-2022 Geoff Graham btw: i noticed that in the editor there is a slight mis-handling of a space after the line number or label. if NO space is included when typing into the editor, the editor (correctly) takes it as implied next time the code is edited, but if a space is present when typed in, the editor (wastefully) explicitly encodes this space when saving. since line numbers and labels are likely to be rarely used anyway, this is inconsequential. sorry for being so pedantic ![]() cheers, rob :-) Edited 2023-02-13 12:26 by robert.rozee |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3292 |
This just shows how long it has been since I dug through this part of MMBasic ![]() I will review it but my main aim these days is to NOT introduce any bugs, which is easy to do given the current size and complexity of the interpreter. Geoff Geoff Graham - http://geoffg.net |
||||
robert.rozee Guru ![]() Joined: 31/12/2012 Location: New ZealandPosts: 2442 |
it may well be safest for Tom to experiment with the idea using his MMB4L first, and only then consider back-porting it to other versions. but i do rather like any idea that can be used to help encourage others to nicely indent their BASIC code! cheers, rob :-) |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |