flat assembler
Message board for the users of flat assembler.
Index
> Compiler Internals > "db (-1) shr 1" results into "value out of ra Goto page 1, 2 Next |
Author |
|
LocoDelAssembly 04 Sep 2010, 19:52
Code: rb (-1) shr X X = 0 <= Error: Invalid value [OK] X = [1, 31] <= Error: Value out of range [MAYBE OK] X = 32 <= Error: Invalid value [SHOULD BE SAME MESSAGE AS ABOVE] X = [33,64] <= Either out of memory or success but the out of memory is OK Although it would be great to have a consistent error message, it is not really a big problem, the maximum attainable RB would be somewhere near 2 GB (or 3GB in 3G/1G systems, and maybe 4 GB in 64-bit OSes??), since fasm is a 32 bit program and does not employ AWE to extend to 64 GB memory. |
|||
04 Sep 2010, 19:52 |
|
LocoDelAssembly 04 Sep 2010, 19:58
http://msdn.microsoft.com/en-us/library/aa366778%28VS.85%29.aspx
So yes, 64-bit systems would allow 4GB space when large address aware flag is set. X = 32 should be working as X = [33,64] then. |
|||
04 Sep 2010, 19:58 |
|
Tomasz Grysztar 04 Sep 2010, 20:04
Code: db (-1) shr 1 Right, that's something I forgot to finish a long time ago. I'm going to fix it now. "xor" operation was not finished as well (only "not" works correctly in current version). LocoDelAssembly: yours is something completely different. |
|||
04 Sep 2010, 20:04 |
|
LocoDelAssembly 04 Sep 2010, 20:39
Mmmhh, I see but I thought I copy&pasted edemko's code (maybe it was changed while I was replying??)
Anyway, what's the problem that needs fixing here? You mean that shr should be arithmetic shift right? |
|||
04 Sep 2010, 20:39 |
|
Tomasz Grysztar 04 Sep 2010, 21:16
LocoDelAssembly wrote: Anyway, what's the problem that needs fixing here? You mean that shr should be arithmetic shift right? When the value has a size explicitly stated (as in "a = byte -1" or "db -1"), fasm does calculations in such a way, that the result is as if the operations were performed on the data of such size (unless there was some "overflow" during the calculations, but that's another story). For example, to yield correct results for such pieces of code: Code: db not 80h dw not 8000h dd not 80000000h However I forgot to finish this feature, namely for "xor" and "shr" operations. The cases where context-dependent calculations are needed with them are very rare, however - that's why it went unnoticed for a long time. |
|||
04 Sep 2010, 21:16 |
|
edemko 04 Sep 2010, 21:22
[quote=Loco]
how did you made the forum allow you to post a blank post? [/quote] Empty line using <Enter>. [quote=Loco] Mmmhh, I see but I thought I copy&pasted edemko's code (maybe it was changed while I was replying??) [/quote] No, you pasted authentic code [quote=Tomasz] fasm has to calculate the value accordingly to the size specified by context [/quote] I thought fasm operated on qwords. |
|||
04 Sep 2010, 21:22 |
|
LocoDelAssembly 04 Sep 2010, 21:44
Oh, I see why I couldn't do that here, only the JavaScript code is preventing that, the server side code does not complain about blank posts at all.
Small clarification: I meant I pasted your code in my FASMW, in the forum I obviously introduced the X variable |
|||
04 Sep 2010, 21:44 |
|
Tomasz Grysztar 04 Sep 2010, 21:46
edemko wrote: I thought fasm operated on qwords. I have these problems (including "rb" error messages) fixed in 1.69.19, but it may take some time with the upload, as I have some connection problems right now. PS. That fasm's expression calculator operates on 64-bit values is in fact a serious flaw - it should operate on 65-bit ones (you may notice an echo of this fact in my fasm 2 presentation from fasmcon 2009). Because of this flaw fasm sometimes allows expressions it should not really allow (like "db 0FFFFFFFFFFFFFF80h"). However it is too late to correct it for 1.x architecture, so I have to live with it. |
|||
04 Sep 2010, 21:46 |
|
Tomasz Grysztar 06 Sep 2010, 18:44
As those fasm's expression calculator peculiarities were never actually documented in detail, I decided to write it down here, so that this information is kept somewhere.
TASM (which was fasm's initial inspiration in many areas) did its integer calculations on 33-bit values. Since those days 32 bits were the usual maximum size for integers, it wasn't a problem that it didn't allow to calculate on 64-bit number, for example. However staying with simple 32 bits was also problematic, because in assembly language one doesn't specify whether a value is signed or unsigned. Therefore one could write "DD 0FFFFFFFFh" or "DD -80000000h" and in both cases expect it to be correct code. In other words, for expression like the one for DD directive, both signed and unsigned value ranges have to be allowed. Therefore TASM was doing its calculations on 33 bits, so that by looking at this additional bits it could know, whether the value was positive or negative, and then check the allowed range accordingly When I was writing fasm, I decided to go a bit further, and I implemented calculations on 64-bit values. That wasn't really because I predicted that 64-bit processors would come, it was years before x86-64 was even first mentioned, and I didn't even think that fasm will be something I would still use at the time of 64-bit processors coming. So fasm's 64 bits were just an improvement over TASM's 33 bits and served the same purpose. If I had envisioned that one day 64 bit will become a size for every-day use (did it?), I would perhaps implement 65-bit calculations instead, analogously to 33-bit ones. Thus this decision had two consequences: one good, and one bad. The good one was that upon coming of x86-64 architecture fasm was ready to deal with 64-bit integer expressions. The bad one was that this was not perfect, because without 65-th bit fasm is not able to distinguish very large positive 64-bit number from a negative one. I'm not saying it is definitely too late to implement 65-bit calculations into fasm. It is possible to do it with some effort; however I'm not sure whether it is really so important (though it would certainly be very satisfying to me to have these things cleaned up). Also there would be a solution of disallowing unsigned positive 64-bit values that don't fit into signed range, but that would the most probably stimulate a wave of bug reports if people started getting error message upon trying to declare quad word with such value. Now back to the topic of range checking, as there is more to it. Allowing both signed and unsigned range applies of course not only to double word values, but to the other quantities as well. So if you define a byte value, you can specify either a unsigned one in range 0 to 0FFh, or a signed one in range -80h to 80h. So effectively byte values are allowed in ranges from -80h to 0FFh. So when you define a value of byte size, fasm first calculates it as 64-bit, and then checks whether it fits into the range -80h to 0FFh. It generally gives the expected results, however it also creates some additional problems. The example of such problem is: Code: db not 80h So how does fasm manage to assemble this? Well, it is aware of the size of desired value from the context (like DB directive or constant definition with BYTE size operator). And in such case it performs the logical operations like "not" appropriately for that size, so that the result does not overflow. And thus with fasm these four instructions are all correct: Code: db not 80h dw not 8000h dd not 80000000h dp not 800000000000h There is a similar case with XOR operations when it has one of arguments negative and one positive and large, like: Code: db (-1) xor 80h Note, however, that if any of the values calculated on is out of range, then fasm does not do this special treating, and calculates it with full 64-bit precision. This means that the only difference between having this feature and not is that some operations are allowed that otherwise would give an error. And it never happens that some expression that would be allowed anyway gives a different result. This is important, as it minimizes the chance that something will be calculated in other way than expected. Also SHR operator is now treated in this special way, to allow things like Code: db (-1) shr 1 However SHL is not affected by the context-derived value size - for the reason that it is sometimes used in the arithmetical sense, and thus is expected to overflow just like the multiplication. Also, if you use SHL to create some bit fields, it is better to detect an overflow and signal it with error, than to silently discard the overflowing bits. |
|||
06 Sep 2010, 18:44 |
|
edemko 07 Sep 2010, 04:12
-"neg" = "-" have priority thus those, like the rest, are cpu instructions protos, really as fasm will execute NEG etc instruction soon. That's why db -$ff should be allowed.
-Why, borders there are?.. -Using 65 arith even, and counting an expression, an intermediate may be a disallowed signed integer(will fasm report every wrong intermediate), and then you add some big value which will not clean bit65 and value stays negative but withing range restrictions(will fasm count transcendent and, having found correct result store it). See, when you controll user input, intermed. must be controlled too. Such controll makes both values pre-operating which is not much convenient. Simulate cpu. Getting a bug report you'll always point at Intel or AMD ;) Next: Code: BIG = $ffffffff'ffffffff db (-1) shr 1 - BIG ;$80 db (-1) shr 1 - 1 ;$7e |
|||
07 Sep 2010, 04:12 |
|
Tomasz Grysztar 07 Sep 2010, 05:14
edemko wrote: -Using 65 arith even, and counting an expression, an intermediate may be a disallowed signed integer(will fasm report every wrong intermediate), and then you add some big value which will not clean bit65 and value stays negative but withing range restrictions(will fasm count transcendent and, having found correct result store it). Code: db -256+128 Code: db (144*343) and 3Fh Code: db (144*343) shr 8 If the similar possibilities applied to 64-bit numbers, it would not be a problem. The larger intermediates you can calculate on, the better (that's why I said on the fasmcon last year that fasm 2.0 would calculate on 129-bit numbers). edemko wrote: Next: |
|||
07 Sep 2010, 05:14 |
|
bitRAKE 07 Sep 2010, 06:28
Why not make FASM 2.0 arbitrary precision? Combined with the context size selection currently used, of course. (Which is a totally awesome way to handle the matter, btw.)
|
|||
07 Sep 2010, 06:28 |
|
Tomasz Grysztar 07 Sep 2010, 09:08
bitRAKE wrote: Why not make FASM 2.0 arbitrary precision? |
|||
07 Sep 2010, 09:08 |
|
edemko 07 Sep 2010, 17:38
Tomasz wrote:
Borland Delphi 7: Code: const ok1:ShortInt = -$80; ok2:ShortInt = -($7f+$01); ok3:ShortInt = $100-$100; // nok1:ShortInt = $80; // nok2:ShortInt = $7f+$01; // nok3:ShortInt = $81; // nok4:ShortInt = -$81; See their brains: value treated positive regardless sign bit. No operand size satisfies $80, $8000, etc. values. Using such approach you are supposed finding new data types: signed and unsigned. Tomasz wrote:
See yourself: like Borland, -129 can not be difined, -$81 too. Hence range checking already works(i found it only now) but, to make it easy, within -128..+255. Now look at -$81, you do not mind it's sign bit too. Tomasz wrote:
Ok, i mean all is fine and no 65 needed. (-super_small) + (-super_small) = super_puper_small, 65 won't help you. Tomasz wrote:
As told over, you do not mention sign bit(let it be a convention). "not $80" gets translated into qword in correct form with high parts zero due the convention. As no minus is specified with "not": -$80 < $ffff'ffff'ffff'ff7f > 255. It means you do all right. There is nothing strange in that high_part_removal as that one is an extension. Byte value is wrong when its extension isn't -1. Seems to be clear... for "not" case at least. Em... to hard. |
|||
07 Sep 2010, 17:38 |
|
edemko 07 Sep 2010, 17:47
shl, shr, or, xor are other cases so i cannot argue/agree with Tomasz as see no bit 65 role here, and a bit tired :(
|
|||
07 Sep 2010, 17:47 |
|
Tomasz Grysztar 07 Sep 2010, 17:48
edemko: either you did not understand what I was writing about or I don't understand what you are writing about. Or perhaps both.
|
|||
07 Sep 2010, 17:48 |
|
DOS386 07 Sep 2010, 23:34
Tomasz Grysztar wrote: As those fasm's expression calculator peculiarities were never actually documented in detail, I decided to write it down here, so that this information is kept somewhere. Quote: (much) Very interesting ... maybe there should be "Compiler Internals FAQ" or even better a set of downloadable docs including this one. There are several such large docs posts by Tomasz here in but they are very hard to find when they sink |
|||
07 Sep 2010, 23:34 |
|
Tomasz Grysztar 08 Sep 2010, 09:57
And I'm adding just a small summary (which I hope may help to understand what is the point here):
We are talking about calculations performed on values of fixed bit size, with signalizing error on overflow. We can then make those operations signed or unsigned, or we alternatively allow both the signed and unsigned results at the price such, that some large positive results won't be distinguishable from the negative ones - I will call this this option to be the "composite". And the summary is: TASM operated on 33-bit signed values (so operated in range -2^32 to 2^32-1), fasm operates on 64-bit composite values (so in range -2^63 to 2^64-1, but with some of the positive results being indistinguishable from negative ones, and therefore with a very poor error checking), and it would be better if it operated on 65-bit signed (in range -2^64 to 2^64-1). And why does fasm use 64-bit composite and not 64-bit signed (which would have no ambiguity problems)? It is because when fasm defines a value of specified size (like BYTE or WORD), it allows it to be in the composite range for that size, and thus analogously it should allow values in composite range for the QWORD size, and this means it has to calculate them in at least 64-bit composite (or at least 65-bit signed) precision. And the special handling of some operations depending on the context-derived size of value is a separate issue, not related to choosing the overall precision of operations. Last edited by Tomasz Grysztar on 08 Sep 2010, 11:43; edited 3 times in total |
|||
08 Sep 2010, 09:57 |
|
Tomasz Grysztar 08 Sep 2010, 10:05
DOS386 wrote: Very interesting ... maybe there should be "Compiler Internals FAQ" or even better a set of downloadable docs including this one. |
|||
08 Sep 2010, 10:05 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.