News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

real or BCD number not allowed

Started by Ficko, July 02, 2010, 04:13:13 PM

Previous topic - Next topic

jj2007

Quote from: Rockoon on July 05, 2010, 03:49:26 PM
Quote from: jj2007 on July 05, 2010, 01:37:28 PM
The "direct" push saves 5 bytes per float... we are stingy here :green

..and an entire cache line

Right, I had not thought of that.

Quote
These sorts of hacks sadden me, because even though they "work" in this specific case, you still cant do preprocessor math.

As a simple for-instance, you might have the constant pi=3.1415 and then (as is common) you also might want to derive 2*pi as another constant. Later you could change pi to = 3.14159265 and that 2*pi constant would reflect the change.

I realize that in this case, the case-specific argument would be "just define pi accurately the first time" .. but what about all the cases where it isnt some universal constant?

We can "immediately" push only REAL4 numbers. The accuracy is bad anyway...

The almost exact PI*1: 3.141592653589793238
The almost exact PI*2: 6.283185307179586477
The args are 6.28318500518798828 and 3.14159250259399414


include \masm32\MasmBasic\MasmBasic.inc
MyTest PROTO :REAL4, :REAL4

Init
Print Str$("The almost exact PI*1: %Jf\n", PI)
Print Str$("The almost exact PI*2: %Jf\n", PI*2)
invoke MyTest, r4(6.283185307179586477=1086918618), r4(3.141592653589793238=1078530010)
Exit

MyTest proc arg1:REAL4, arg2:REAL4
  Print Str$("The args are %If and ", s:arg1), Str$("%If", s:arg2), CrLf$
  ret
MyTest endp

end start

clive

Quote from: Rockoon
These sorts of hacks sadden me, because even though they "work" in this specific case, you still cant do preprocessor math.

Indeed, most all assemblers seem to have universally crappy floating point support. They know they have to support it, but clearly have no real interest. Evidently most assembler writers haven't been forced to "eat the dog food".

Here, Microsoft C cheats in it's ASM/COD file to push REAL4 and REAL8 values. Unfortunately I can't see a way of casting, or any low level hack for the MACRO system to delve into the assemblers' internals (beyond the DB 68h; REAL4 x). I really wish something like "PUSH HIGH32(REAL8(x))" would work.

PUBLIC _main
_TEXT SEGMENT
_main PROC NEAR

; 17   : {

  00035 55 push ebp
  00036 8b ec mov ebp, esp

; 18   :   out(3.141592653589793238);

  00038 68 db 0f 49 40 push 1078530011 ; 40490fdbH
  0003d e8 00 00 00 00 call _out
  00042 83 c4 04 add esp, 4

; 19   :
; 20   :   outdbl(3.141592653589793238);

  00045 68 fb 21 09 40 push 1074340347 ; 400921fbH
  0004a 68 18 2d 44 54 push 1413754136 ; 54442d18H
  0004f e8 00 00 00 00 call _outdbl
  00054 83 c4 08 add esp, 8

; 21   :
; 22   :   return(0);

  00057 33 c0 xor eax, eax

; 23   : }

  00059 5d pop ebp
  0005a c3 ret 0
_main ENDP
_TEXT ENDS



Quote from: Raymond
I've always wondered why some people do not adhere to the KISS principle.

In this example, why not simply initialize it as a global variable in the .data section and get it from there???

Because it's almost always slower and takes more memory. Which can be a pain if you are constrained by ROM space, and CPU speed. If things were passed by address, and some effort was made to fold the constant literal pool, I could make a case for REAL8 or REAL10. Passing a REAL4 constant as anything but the value itself on a 32-bit machine is one abstraction too many. I can see the memory literal working if the FPU was being used directly (x87 instruction using float register and memory variable) and needed to load from memory, but the stacked values are in memory by the time the FPU is invoked.

The key thing here is the ASSEMBLER should make this SIMPLE and EASY, it does not, and that is a real pity.


I'm banging my head on some 68K issues (68EC020 + 68881/68882) of a similar nature. The compiler generates code that moves a 32-bit constant stored at a memory location (32-bit), the opcodes take the same amount of space as just writing the constant directly, and frankly it costs more cycles to get the address, and then read the contents. It will even do this for 64-bit values, and does not fold constants. The code generator was apparently written by an intern and had not owned an ST/AMIGA, or had one in the house.

JJ might enjoy this particularly stellar 68K code fragment from the Fortran (circa 1993) compiler zeroing some REAL*8 values...

  122  9:000001B2  6740                  BEQ.S L68
  123  9:000001B4  42AA001C              CLR.L 28(A2)
  124  9:000001B8  23F9000000040000      MOVE.L L120+4,npk_+28
  124  9:000001C0  001C
  125  9:000001C2  23F9000000000000      MOVE.L L120,npk_+24
  125  9:000001CA  0018
  126  9:000001CC  23F90000000C0000      MOVE.L L121+4,npk_+36
  126  9:000001D4  0024
  127  9:000001D6  23F9000000080000      MOVE.L L121,npk_+32
  127  9:000001DE  0020
  128  9:000001E0  23F9000000140000      MOVE.L L122+4,npk_+44
  128  9:000001E8  002C
  129  9:000001EA  23F9000000100000      MOVE.L L122,npk_+40
  129  9:000001F2  0028
  130                                   L68:
  131
  132  9:000001F4  4CEE3C1CFFE4          MOVEM.L -28(A6),D2/D3/D4/A2/A3/A4/A5
  133  9:000001FA  4E5E                  UNLK A6
  134  9:000001FC  4E75                  RTS

  143  2:00000000                        SECTION 2
  144  2:00000000  00000000             L120: DC.B 0,0,0,0
  145  2:00000004  00000000              DC.B 0,0,0,0
  146  2:00000008  00000000             L121: DC.B 0,0,0,0
  147  2:0000000C  00000000              DC.B 0,0,0,0
  148  2:00000010  00000000             L122: DC.B 0,0,0,0
  149  2:00000014  00000000              DC.B 0,0,0,0
  150  2:00000018  00000000             L123: DC.B 0,0,0,0
  151  2:0000001C  00000000              DC.B 0,0,0,0


I'm glad they didn't use a CLR.L on memory (68K will do a pointless read before write), but I was writing better code than this in high school ten years before this compiler was released.
It could be a random act of randomness. Those happen a lot as well.

jj2007

Quote from: clive on July 06, 2010, 08:25:20 PM
JJ might enjoy this particularly stellar 68K code fragment from the Fortran (circa 1993) compiler zeroing some REAL*8 values...

I do :bg
MOVEM.L -28(A6),D2/D3/D4/A2/A3/A4/A5 - the flexible equivalent to pushad/popad; but remember you have no influence on the order ;-)

Re push Real8: I can't see an easy way to push immediate values using invoke, but the edx::eax pair is nice to memory and cache lines. So I added this feature to RichMasm/MasmBasic, too: Select r8(3.141592653589793238=?), press F1, see r8(3.141592653589793238=1074340347/1413754136)

include \masm32\MasmBasic\MasmBasic.inc
MyProc8 PROTO :REAL8
MyProc4 PROTO :REAL4

r8 MACRO arg
LOCAL is, slash
  is INSTR <arg>, <=>
  slash INSTR <arg>, </>
  if is
mov edx, @SubStr(<arg>, is+1, slash-is-1)
  endif
  mov eax, @SubStr(<arg>, slash+1)
  EXITM <edx::eax>
ENDM

Init
Print Str$("The real PI: %Jf\n", PI)
invoke MyProc8, r8(3.141592653589793238=1074340347/1413754136)
invoke MyProc4, r4(3.141592653589793238=1078530010)
Exit
MyProc8 proc arg8:REAL8
  Print Str$("Real8: I got %Jf\n", arg8)
  ret
MyProc8 endp
MyProc4 proc arg4:REAL4
  Print Str$("Real4: I got %Jf\n", s:arg4)
  ret
MyProc4 endp
end start


The real PI: 3.141592653589793238
Real8: I got 3.141592653589793116
Real4: I got 3.141592502593994140