OSDev.org https://forum.osdev.org/ |
|
Tutorial: Printing FPU Floating Numbers in Pure Assembly https://forum.osdev.org/viewtopic.php?f=13&t=31357 |
Page 1 of 2 |
Author: | ~ [ Fri Feb 10, 2017 8:36 pm ] |
Post subject: | Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Link (Public Domain License): http://devel.archefire.org/forum/viewtopic.php?p=4143&hl=en#p4143 EXE: http://devel.archefire.org/tmp/FPU_float_print_demo.zip http://archive.org/download/x86_FPU_Programming_0002/FPU_float_print_demo.zip Video description: http://www.youtube.com/watch?v=Xrfri-hKYbg This is a tutorial with a sample Win32 program and Assembly utility functions that convert a floating point number from the FPU to print it. The function uses the FPU itself to convert each digit into ASCII, first the integer part and then the floating point part. It also has an ASCII string reversion utility function since the integer string representation is generated backwards. The function reads the first and last character at a time in AL and AH respectively, then uses XCHG and writes them back to revert the string as if we flipped a transparent sheet and could see the string values already reverted. Then it increases the start of string pointer and decreases the end of string pointer to continue the reversion. If the string has odd size or if it reached the last two bytes (size divided by 2 in the function), it will stop because it makes no sense to try to revert the center byte, for example, in a 3-byte string. I have put it in my external website since I have full control there to edit the HTML, the links and maintain it properly. I put it here since I realize that it will be an useful snippet to actually learn how to finally use the FPU usefully by being able to calculate and then print the results right away to know whether we calculated correctly. |
Author: | matt11235 [ Sat Feb 11, 2017 4:11 am ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
~ wrote: Video description: I don't think that you understand the purpose of a video.
http://www.youtube.com/watch?v=Xrfri-hKYbg |
Author: | gerryg400 [ Sat Feb 11, 2017 4:31 am ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Hi ~, you should read this. |
Author: | ~ [ Sat Feb 11, 2017 5:44 pm ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
It's always good to read the available conversion methods. Here is what I did: I used the full 80-bit precision of the FPU. I turned off rounding in the FPU (I used Truncate Mode -no rounding- in the Control Word). I used FPREM to get the modulo division by 10 to get each digit of the integer part. I used FISTTP or FISTP to extract the integer part without any rounding at all. (FISTTP (supposedly from SSE3; also ignores the rounding mode form the Control Word although I set it to truncate anyway so it should work with FISTP too) or FISTP (supposedly more compatible and makes use of the rounding mode from the Control Word)). I multiplied the fractional part by 10 to get each one of its digits. To get the fractional part only, I used FCHS to change the sign of a copy of the integer part and substract by adding the full number with the integer part only with inverted sign. Finally, to each digit I got, I added the value 48 with the FPU itself to convert to ASCII digit, saved the result to memory as an integer, and obtained the first byte with the CPU. With this I converted each digit to ASCII to then save those string digits to the final string. |
Author: | Brendan [ Sun Feb 12, 2017 3:55 am ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Hi, ~ wrote: Here is what I did: Tell me what happens when you try to print the number 9223372036854775808.0. Cheers, Brendan |
Author: | ~ [ Sun Feb 12, 2017 11:24 am ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Brendan wrote: Hi, Only garbage.~ wrote: Here is what I did: Tell me what happens when you try to print the number 9223372036854775808.0. Cheers, Brendan I can only seem to print numbers between 9223372036854775807.5 and -9223372036854775807.5. JavaScript rounds it to 9223372036854776000 which seems a big error. The program also had a bug where I forgot to pop the FPU stack once, so it could only print 6 integer digits. I corrected it and reuploaded it. Thanks for the exercise. |
Author: | gerryg400 [ Sun Feb 12, 2017 6:29 pm ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
~ wrote: JavaScript rounds it to 9223372036854776000 which seems a big error. Well not really. It's correct to about 16 decimal places while your function returns garbage. Did you actually read the paper I pointed to?
|
Author: | Brendan [ Sun Feb 12, 2017 6:52 pm ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Hi, ~ wrote: Brendan wrote: Tell me what happens when you try to print the number 9223372036854775808.0. Only garbage.I can only seem to print numbers between 9223372036854775807.5 and -9223372036854775807.5. This is because the range of the 64-bit signed integer is -9223372036854775808 to +9223372036854775807; so the "FISTP" (to get the integer part) causes problems for anything outside that range. Fortunately, for "double precision", the significand only has 52 bits (or 53 bits if you include the implied bit); which means that any number outside the range of a 64-bit signed integer must be an integer. More specifically; for "double precision", any number where the exponent is not less than 53 must be an integer. This means that you can check if the biased exponent is >= 53+1023 and use a faster/simpler "integers only" method. Unfortunately, for "extended precision", the significand has 63 bits (or 64 bits if you include the implied bit). In this case any number where the exponent is not less than 64 must be an integer; and if the exponent is 63 then the number may not be an integer and will be outside the range of a 64-bit signed integer. However, if the exponent is 63 then the least significant bit of the significand will indicate if there is no fraction or if the fraction is 0.5. This means that:
However... Displaying numbers properly requires internationalisation. Programmers have been "perverted" by prolonged use of crappy programming languages and crappy standard libraries, which have traditionally failed to accept properly formatted numbers as input (in the source code itself, and in functions like "atoi()" used at run-time) and failed to convert numbers to strings (for display, etc) properly. Large numbers are too error prone (the risk of miscounting the digits is quite high), so normal humans put "thousands separators" in their numbers. Unfortunately different people use a different "thousands separator character" and a different "decimal point character". For example, you shouldn't ever display "9223372036854775807.5" but should display either "9,223,372,036,854,775,807.5" or "9.223.372.036.854.775.807,5" instead. It's relatively easy to split a number into groups using "number % 1000" and "number / 1000"; so that you have none or more integer groups (from 0 to 999) and none or one group that contains the fractional bits (from 0.000.. to 999.99999..). This avoids all of the problems for large numbers (no group is >= 1000); and makes it easier to improve performance with SIMD (because you can do multiple groups in parallel); and makes it easier to generate the digits in the correct order (e.g. "temp = group % 100; digit1 = group/100; digit2 = temp/10; digit3 = temp % 10; ") and avoid reversing the characters after. Cheers, Brendan |
Author: | Brendan [ Sun Feb 12, 2017 7:16 pm ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Hi, gerryg400 wrote: Did you actually read the paper I pointed to? I didn't - I glanced at it, and then realised how much I "dislike" mathematicians. For fun... Programming (as a field of expertise) has only really existed for about 60 years. It took less than 30 years for programmers to realise that (except for a few cases - e.g. the use of 'i' and 'j' for induction variables in simple loops, and 'x', 'y' and 'z' in coordinate systems) single letter variable names are unmaintainable/unreadable trash. In comparison, mathematics has been around for over 3000 years and in all that time they still haven't realised that single letter variable names are extremely bad. After so much time it's unreasonable to assume nobody has ever thought about making mathematics (the language) readable. You have assume that their prolonged negligence is a deliberate and malicious attempt to annoy everyone. Cheers, Brendan |
Author: | Schol-R-LEA [ Sun Feb 12, 2017 9:30 pm ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Some points to be made:
|
Author: | Brendan [ Sun Feb 12, 2017 11:04 pm ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Hi, Schol-R-LEA wrote:
Sure; in mathematics "variables" typically can't be varied (not in an "x = x + 1" way), and yet somehow it's programmers that got it wrong despite being able to distinguish between "constants" (that don't vary) and "variables" (that do vary). Schol-R-LEA wrote:
I still consider mathematics to be a language, even though it might or might not be more technically correct to call it a group of languages (in the same way that "assembly language" applies to many different dialects of assembly). It's not a strictly defined language, but few languages are strictly defined (it's only really languages that need to be understood by machines, like programming languages, that are strictly defined; and even then they still evolve via. non-standard extensions and standardised versions). Schol-R-LEA wrote:
There are existing symbols that could be used (and would be understood) for multiplication if mathematicians tried to correct the stupidity that's built into the design of their language/s. For example, "area" could unambiguously be a single (4-letter) name, while "a.r.e.a" and "a×r×e×a" (and whatever else these inconsistent fools may use for a multiplication sign) denotes multiplication of four single-letter variables. Cheers, Brendan |
Author: | MichaelFarthing [ Mon Feb 13, 2017 2:59 am ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Brendan wrote: For example, "area" could unambiguously be a single (4-letter) name, while "a.r.e.a" and "a×r×e×a" (and whatever else these inconsistent fools may use for a multiplication sign) denotes multiplication of four single-letter variables. That's rich coming from a representative of a community that has added to that initial ambiguity by adopting yet another symbol for multiplication (*) |
Author: | Sik [ Mon Feb 13, 2017 3:16 am ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
For the record, the whole issue of multiletter variables in maths could be worked around by using cursive (where letters are always joined together), then you'd know if two letters are separate variables or not by whether the letters themselves are separated. Heck, it already has multiletter stuff for some operators (e.g. sin). That's the least of the problems with math though, especially since the meaning of each letter is usually explained in a paragraph next to the equation. The bigger problem is just how horribly complex they can get with all those symbols (while programming normally only uses the most basic operations, using actual words for more complex ones). That certainly can make any even remotely complex equation a pain to read unless you're a mathematician (and possibly even if you are). Brendan wrote: Displaying numbers properly requires internationalisation. Programmers have been "perverted" by prolonged use of crappy programming languages and crappy standard libraries, which have traditionally failed to accept properly formatted numbers as input (in the source code itself, and in functions like "atoi()" used at run-time) and failed to convert numbers to strings (for display, etc) properly. As usual, this is a problem harder than it sounds, since numbers meant for computers (e.g. stored in a file) are different than numbers to be shown on screen. And when it comes to separators, different regions have different requirements (not just . vs , there's also other symbols, or how many digits to group, or how to show the sign, or even which characters are to be used for digits, etc.). And that's ignoring stuff like padding and such, or the fact your program may be using a different language than the system's (e.g. because it wasn't translated into it yet), so you may need to explicitly set the formatting locale. All this really should just be part of a formatting string. ...incidentally, the standard C library already handles all this (look up the locale stuff, most of the lconv structure is dedicated to number formatting in fact). It's just that nobody bothers to use it. Brendan wrote: It's relatively easy to split a number into groups using "number % 1000" and "number / 1000"; Eh, depends on how long is the number, I suppose that for your average number is OK, but if the number is huge then it may be better to just count characters as you generate the string. Either one works, I guess (use whichever is easier for the case). MichaelFarthing wrote: That's rich coming from a representative of a community that has added to that initial ambiguity by adopting yet another symbol for multiplication (*) Blame ASCII for that. And many early programming language did use either × or · instead. Kind of wishing some of the ASCII control codes were just more glyphs. Turning FS/GS/RS/US into ↑↓←→ would have been great (and we could be using ← instead of = for assignment, yes I know other languages use := but it looks awkward). |
Author: | alexfru [ Mon Feb 13, 2017 4:12 am ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Sik wrote: For the record, the whole issue of multiletter variables in maths could be worked around by using cursive (where letters are always joined together), then you'd know if two letters are separate variables or not by whether the letters themselves are separated. Heck, it already has multiletter stuff for some operators (e.g. sin). Cursive is cursed! Haven't used it for 20+ years. Left it at school. |
Author: | Brendan [ Mon Feb 13, 2017 4:15 am ] |
Post subject: | Re: Tutorial: Printing FPU Floating Numbers in Pure Assembly |
Hi, Sik wrote: Brendan wrote: Displaying numbers properly requires internationalisation. Programmers have been "perverted" by prolonged use of crappy programming languages and crappy standard libraries, which have traditionally failed to accept properly formatted numbers as input (in the source code itself, and in functions like "atoi()" used at run-time) and failed to convert numbers to strings (for display, etc) properly. As usual, this is a problem harder than it sounds, since numbers meant for computers (e.g. stored in a file) are different than numbers to be shown on screen. If it's meant for computers it becomes easy - use binary instead of text. If you must use text, then go "concise and precise" with hexadecimal (e.g. maybe "0x1234567 >> 16"). Sik wrote: And when it comes to separators, different regions have different requirements (not just . vs , there's also other symbols, or how many digits to group, or how to show the sign, or even which characters are to be used for digits, etc.). And that's ignoring stuff like padding and such, or the fact your program may be using a different language than the system's (e.g. because it wasn't translated into it yet), so you may need to explicitly set the formatting locale. All this really should just be part of a formatting string. Yes; multiple options (even using metric prefixes if you like); but the "split into groups" concept helps with most of them. Sik wrote: ...incidentally, the standard C library already handles all this (look up the locale stuff, most of the lconv structure is dedicated to number formatting in fact). It's just that nobody bothers to use it. I'm not sure that it's possible for someone to care enough about Internationalisation to be willing to use what C provides, while also caring so little about Internationalisation that they're willing to use what C provides. Sik wrote: MichaelFarthing wrote: That's rich coming from a representative of a community that has added to that initial ambiguity by adopting yet another symbol for multiplication (*) Blame ASCII for that. And many early programming language did use either × or · instead. Kind of wishing some of the ASCII control codes were just more glyphs. Turning FS/GS/RS/US into ↑↓←→ would have been great (and we could be using ← instead of = for assignment, yes I know other languages use := but it looks awkward). I'd be tempted to blame ASCII for "lower case x" (e.g. "1920x1200") too. Cheers, Brendan |
Page 1 of 2 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |