How can you push or mov a real4 number in MASM? ::)
push 3.4 ;bad
push real4 ptr 2.0 ;bad
http://www.masm32.com/board/index.php?topic=6349.0
All right MASM sucks can JWASM do that? :P
Zooba's macro is quite a good option:
movr4 MACRO dest:REQ, src:REQ
mov dest, 0BADF00Dh
ORG $-4
REAL4 src
ENDM
The same in function format would be great, but it seems not so straightforward. Unless we can do the REAL4 to DWORD conversion in assembly time calculations.
As an intermediate solution:
pushr4 MACRO src:REQ
push 0BADF00Dh
ORG $-4
REAL4 src
ENDM
Just saw that Ultrano had it already:
pushfl macro float1
db 68h ; "push immediate dword"
real4 float1
endm
i like the last one :P
nothing like writing pure machine language
Quote
Zooba's macro is quite a good option:
Yes but I need some enhancement. :bg
I have this:
%echo VarConst
-10*2
now I have to push it as a real4.
How I can get the calculation back in assembler time (-20) So I can add ".0" - VarConst CATSTR -20,<.0> - before pushr4 ? ::)
Never mind figured out.
Tmp EQU VarConst
%CatStr(<%Tmp>)
gives -20 :dance:
I am still saddened that none of the assemblers that I am aware of can do simple math on floating point preprocessor variables.
i don't think it's that simple :P
i'd love to see what you have, though :U
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??? :dazzled: For all practical purposes, it's about the same amount of typing!!!
.data
fl3p4 REAL4 3.4
.code
push fl3p4
Quote from: raymond on July 04, 2010, 02:39:51 AM
I've always wondered why some people do not adhere to the KISS principle.
Raymond, the goal is a direct invoke MyProc, 123.456, -12.45e3 in the sense of
push an immediate dword aka -12.45e3
push an immediate dword aka 123.456
call MyProc
i.e. posters don't want to push a memory reference but rather the number itself as an "immediate real4".
If I were a lot better at maths, I'd be tempted to do the translation from123.456 to its hex equivalent in a macro :bg
Rockoon's remark on preprocessing inspired me to teach RichMasm (http://www.masm32.com/board/index.php?topic=12460) something useful: Calculate the hex equivalent.
Imagine you have the following full-fledged Win32 application in PureMasmTM:
include \masm32\MasmBasic\MasmBasic.inc
MyTest PROTO :REAL4, :REAL4
Init
invoke MyTest, r4(-12.34567e-9=-1303111467), r4(987.654=1148643803)
Exit
MyTest proc arg1:REAL4, arg2:REAL4
Print Str$("The args are %f and ", s:arg1), Str$(s:arg2)
ret
MyTest endp
end start
Output: The args are -1.234567e-08 and 987.6540
How does it work?
1. Select the red part in invoke MyTest, r4(-12.34e5=?), r4(987.654=1148643803)
2. Press F1
3. See invoke MyTest, r4(-12.34e5=-912874880), r4(987.654=1148643803) - ready for assembly
:bg
The r4 macro is part of MasmBasic:
r4 MACRO arg
LOCAL is
is INSTR <arg>, <=>
if is
EXITM @SubStr(<arg>, is+1)
else
EXITM <arg>
endif
ENDM
QuoteIf I were a lot better at maths, I'd be tempted to do the translation from123.456 to its hex equivalent in a macro
BUT, it's so much easier to let the assembler transform it in the data section, and you don't need to know any of the required math. :bdg You then refer to it as a pointer to it's address or as it's actual value, whichever suits your needs.
Quote from: raymond on July 05, 2010, 12:18:47 AM
BUT, it's so much easier to let the assembler transform it in the data section, and you don't need to know any of the required math. :bdg You then refer to it as a pointer to it's address or as it's actual value, whichever suits your needs.
The "direct" push saves 5 bytes per float... we are stingy here :green
Quote from: jj2007 on July 05, 2010, 01:37:28 PM
Quote from: raymond on July 05, 2010, 12:18:47 AM
BUT, it's so much easier to let the assembler transform it in the data section, and you don't need to know any of the required math. :bdg You then refer to it as a pointer to it's address or as it's actual value, whichever suits your needs.
The "direct" push saves 5 bytes per float... we are stingy here :green
..and an entire cache line
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?
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
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.
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