flat assembler
Message board for the users of flat assembler.

 Index > Main > Converting arithmetic expressions to Assembly Goto page Previous  1, 2
Author
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 18264
revolution
Or just use FCHS and then any implementation details about storage and number formats can be handled by the hardware.

BTW: xor changes the sign, it is not equivalent to FABS.
11 Nov 2018, 10:45
Furs

Joined: 04 Mar 2016
Posts: 1657
Furs
revolution wrote:
Or just use FCHS and then any implementation details about storage and number formats can be handled by the hardware.

BTW: xor changes the sign, it is not equivalent to FABS.
Oh, I thought you wanted to flip the sign in case the power was odd/even. My bad.

Then of course you have to use and instead, with 0x7F, but yeah.
11 Nov 2018, 11:06
fasmnewbie

Joined: 01 Mar 2011
Posts: 555
fasmnewbie
Furs wrote:
I mean MSB = most significant byte. In your case it should be "most significant DWORD".

When people refer to MSB, people talk about byte position, NOT a byte quantity. In any operand size larger than a byte, there always exists 2 important properties of that operand: its LSB and MSB. MSB always assumes the highest byte position of any given operand. This is pretty basic.
I don't think you understand how floating format is laid out in memory or in a GPR. I also doubt your understanding on how addressing modes work. Here's the real layout of how floating point is parsed in memory;
Code:
```x dq -45.345

mov al,byte[x+7]   ;this approaches the MSB if you want to extract the highest byte
and al,0x7f           ;flip it
mov byte[x+7],al  ;copy it back to MSB

or,

btr dword[x+4],31 ;flips the bit 31 of the upper half of the REAL8.    ```

While XOR and AND also work, sometimes it is better being more explicit of what you instruction trying to do. For example in this case, BTR stands for Bit Test and Reset. It's much more clearer and descriptive.

If you have access to my BASELIB routines, you get to see what you're talking about on-the-fly. You don't need "geometry" of some sort to see how a REAL8 data are parsed into memory.

Code:
```;This is "sbase32w.asm"
format PE console
include 'win32axp.inc'
entry main

x       dq -45.345

main:
push    x
call    fpdinfo
call    prnline

btr     dword[x+4],31  ;reset bit 31 of the upper portion of x

push    x
call    fpdinfo
call    prnline

push    x
call    prndbl
call    prnline

push    x
push    64
call    memview

call    halt
call    exitx     ```

With this output
Code:
```C046AC28F5C28F5C
1.10000000100.01101010110000101000-11110101110000101000111101011100
Sign: 1
Exp : +5
Mant: 1.41703125

4046AC28F5C28F5C
0.10000000100.01101010110000101000-11110101110000101000111101011100
Sign: 0
Exp : +5
Mant: 1.41703125

45.345
00401000| 5C 8F C2 F5 28 AC 46 40 |+7|+7
00401008| 00 00 00 00 00 00 00 00 |+F|+15
00401010| 00 00 00 00 00 00 00 00 |+17|+23
00401018| 00 00 00 00 00 00 00 00 |+1F|+31
00401020| 00 00 00 00 00 00 00 00 |+27|+39
00401028| 00 00 00 00 00 00 00 00 |+2F|+47
00401030| 00 00 00 00 00 00 00 00 |+37|+55
00401038| 00 00 00 00 00 00 00 00 |+3F|+63    ```

See how the value changes in memory via memview output using the correct addressing mode.
11 Nov 2018, 11:33
fasmnewbie

Joined: 01 Mar 2011
Posts: 555
fasmnewbie
revolution wrote:
Or just use FCHS and then any implementation details about storage and number formats can be handled by the hardware.

BTW: xor changes the sign, it is not equivalent to FABS.

FCHS involves branching. While it sounds convenient it's probably not the best option here.
11 Nov 2018, 11:44
fasmnewbie

Joined: 01 Mar 2011
Posts: 555
fasmnewbie
Furs wrote:
revolution wrote:
Or just use FCHS and then any implementation details about storage and number formats can be handled by the hardware.

BTW: xor changes the sign, it is not equivalent to FABS.
Oh, I thought you wanted to flip the sign in case the power was odd/even. My bad.

Then of course you have to use and instead, with 0x7F, but yeah.

Don't let yourself down
XOR does work if you pit it against the entire DWORD. It just doesnt work against the MSB that way.

Here's another example, showcasing the AND and XOR to flip the sign bit of a REAL8. Still using "sbase32w.asm" source;
Code:
```x dq -0.02345

;and     dword[x+4],0x7fffffff
xor     dword[x+4],0x80000000
push    x
call    prndbl     ;Sign bit is reset, using either one of the above    ```
11 Nov 2018, 12:09
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 18264
revolution
fasmnewbie wrote:
FCHS involves branching. While it sounds convenient it's probably not the best option here.
The behaviour will be implementation dependant. The instruction byte length is probably shorter than using the CPU instructions, so if performance is a concern then it could be more cache friendly, that would depend upon the application it is used in.
11 Nov 2018, 12:18
Furs

Joined: 04 Mar 2016
Posts: 1657
Furs
fasmnewbie wrote:
When people refer to MSB, people talk about byte position, NOT a byte quantity. In any operand size larger than a byte, there always exists 2 important properties of that operand: its LSB and MSB. MSB always assumes the highest byte position of any given operand. This is pretty basic.
I don't think you understand how floating format is laid out in memory or in a GPR. I also doubt your understanding on how addressing modes work. Here's the real layout of how floating point is parsed in memory;
Code:
```x dq -45.345

mov al,byte[x+7]   ;this approaches the MSB if you want to extract the highest byte
and al,0x7f           ;flip it
mov byte[x+7],al  ;copy it back to MSB

or,

btr dword[x+4],31 ;flips the bit 31 of the upper half of the REAL8.    ```
But why +4 and not +7? The position of the MSB byte is x+7. Literally. Doesn't matter the access mode.

You are truncating it to a 4-byte alignment (dword), but in fact:
Code:
`btr dword[x+7],31    `
is a perfectly valid instruction and works (and it's what MSB means btw).

There's no reason to truncate a byte's position based on what you are accessing with, because x86 doesn't require aligned memory access (except for rare cases).

So saying "MSB" in this context is very confusing, IMO. Should be "most significant DWORD" as I said.

EDIT: BTW I am aware that it SHOULD be x+4, I'm not disagreeing with you. Just saying that you used the "your base's MSB" as the address which is confusing cause it means [x+7] in this case, which is wrong. i.e. just a matter of what you said, not what you meant

Last edited by Furs on 11 Nov 2018, 18:42; edited 2 times in total
11 Nov 2018, 15:40
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 18264
revolution
Furs wrote:
But why +4 and not +7? The position of the MSB byte is x+7. Literally. Doesn't matter the access mode.
"btr dword[x+7],31" will alter bit 7 of the byte at x+10.
11 Nov 2018, 15:44
UniverseIsASimulation

Joined: 23 Sep 2016
Posts: 32
UniverseIsASimulation
It seems like there are more than one bug in the web-app. If I enter the arithmetic expression:
Code:
`pow(abs(x),y)*((x<0&mod(y,2)=1)*(-1)+(x>0|mod(y,2)=0)*1+((x<0&not(mod(y,1)=0)&(0/0))))    `

Transpiled into JavaScript and then executed (which is what the "Interpret" button does), it behaves like the "pow" function for all inputs. However, the compiler output is this:
Code:
```finit
fld dword [y]
mov [result],2f
fld dword [result]
fxch
fprem
fxch
fstp dword [result]
mov [result],1f
fld dword [result]
fcomip st1
fstp dword [result]
jne l640924
fld1
jmp l564953
l640924:
fldz
l564953:
fld dword [x]
mov [result],0f
fld dword [result]
fcomip st1
fstp dword [result]
jna l337650
fld1
jmp l814480
l337650:
fldz
l814480:
fxch
fistp dword [result]
mov eax,[result]
fistp dword [result]
and [result],eax
fild dword [result]
mov [result],0f
fld dword [result]
mov [result],1f
fld dword [result]
fsubp st1,st0
fmulp st1,st0
fld dword [y]
mov [result],2f
fld dword [result]
fxch
fprem
fxch
fstp dword [result]
mov [result],0f
fld dword [result]
fcomip st1
fstp dword [result]
jne l730422
fld1
jmp l471695
l730422:
fldz
l471695:
fld dword [x]
mov [result],0f
fld dword [result]
fcomip st1
fstp dword [result]
jnb l46226
fld1
jmp l580080
l46226:
fldz
l580080:
fxch
fistp dword [result]
mov eax,[result]
fistp dword [result]
or [result],eax
fild dword [result]
mov [result],1f
fld dword [result]
fmulp st1,st0
fld dword [y]
mov [result],1f
fld dword [result]
fxch
fprem
fxch
fstp dword [result]
mov [result],0f
fld dword [result]
fcomip st1
fstp dword [result]
jne l920163
fld1
jmp l751054
l920163:
fldz
l751054:
fld1
fxch
fsubp st1,st0
fld dword [x]
mov [result],0f
fld dword [result]
fcomip st1
fstp dword [result]
jna l399314
fld1
jmp l871526
l399314:
fldz
l871526:
fxch
fistp dword [result]
mov eax,[result]
fistp dword [result]
and [result],eax
fild dword [result]
mov [result],0f
fld dword [result]
mov [result],0f
fld dword [result]
fdivp st1,st0
fistp dword [result]
mov eax,[result]
fistp dword [result]
and [result],eax
fild dword [result]
fld dword [x]
fabs
fld dword [y]
fxch
fld1
fxch
fyl2x
fldl2e
fdivp st1,st0
fmulp st1,st0
fldl2e
fmulp st1,st0
fld1
fscale
fxch
fld1
fxch
fprem
f2xm1
fmulp st1,st0
fxch
fmulp st1,st0
fstp dword [result]
```

That, if compiled with FASM and run, doesn't give the correct results. Any idea what's going on?
11 Nov 2018, 16:12
Furs

Joined: 04 Mar 2016
Posts: 1657
Furs
revolution wrote:
Furs wrote:
But why +4 and not +7? The position of the MSB byte is x+7. Literally. Doesn't matter the access mode.
"btr dword[x+7],31" will alter bit 7 of the byte at x+10.
I know, that's exactly what I mean.

He said [your base's MSB] to use in place of dword [x+4] which is confusing since x+4 is not the MSB.
11 Nov 2018, 18:27
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 18264
revolution
So x+4 is the MSD?

Anyhow, just use FCHS or FABS, they'll get the job done without this kind of confusion.
11 Nov 2018, 18:31
fasmnewbie

Joined: 01 Mar 2011
Posts: 555
fasmnewbie
Quote:
EDIT: BTW I am aware that it SHOULD be x+4, I'm not disagreeing with you. Just saying that you used the "your base's MSB" as the address which is confusing cause it means [x+7] in this case, which is wrong. i.e. just a matter of what you said, not what you meant Razz

Yeah, I can see where your confusion came from. It's about trying to match the idea of a "byte quantity" to a "dword" memory operand. I understand that problem. I was once there when I was completely as clueless to separate the idea of addressing modes from operand sizes. Thank god for the AMD manuals!
12 Nov 2018, 11:19
fasmnewbie

Joined: 01 Mar 2011
Posts: 555
fasmnewbie
universe

your code is too long for us to even begin with. Give a smaller test case so we can at least enjoy it in smaller pieces. Perhaps start with label names?
12 Nov 2018, 11:28
fasmnewbie

Joined: 01 Mar 2011
Posts: 555
fasmnewbie
Universe, here, I embedded the output above into the "sbase32w.asm" source file. You can run the program as it is and get to use the FPU-specific routines in there. For example, I inserted multiple calls to "fpu_stack" at certain jump points to confirm the transitions from 1 "label" to another. In the end I call "prnflt" routine to print the final result. I didn't make any modifications to the above output.

You can also insert calls to "fpu_stack" at suspected faulty lines to see the content of the FPU any time.

For x = 5.4, y=3.4 the final answer is 309.1284.

Is this expected?

P/s Attachment will be deleted soon, because my quota doesn't look good, I think.

Last edited by fasmnewbie on 13 Nov 2018, 14:27; edited 1 time in total
12 Nov 2018, 11:49
UniverseIsASimulation

Joined: 23 Sep 2016
Posts: 32
UniverseIsASimulation
Yes, but for x=-2 and y=1.5, it returns 0. I expected it to return NaN.
12 Nov 2018, 16:07
fasmnewbie

Joined: 01 Mar 2011
Posts: 555
fasmnewbie
Universe, it shouldn't return NaN because you already set it to FABS. Returning 0.0 is expected. It is now come down to your own set of rules against user input, at least for POW function taking negative base. I don't see anything wrong there.

For my own fpow function, I immediately set it to #err for negative base because I knew something confusing like this could happen.
12 Nov 2018, 18:12
UniverseIsASimulation

Joined: 23 Sep 2016
Posts: 32
UniverseIsASimulation
Anyway, I've improved my compiler using the Duktape framework to be able not only to translate single directives from my own programming language into Assembly, but to also be able to translate entire simple programs stored in files. Here is one of the first programs I've written in the first programming language I've made myself:
Code:
```;Advanced example: implementing the permutation algorithm.
AsmStart
debug=0
macro pushIntToStack x
{
sub esp,4
fld dword [x]
fistp dword [esp]
}
macro pushPointerToStack x
{
sub esp,4
lea ebx,[x]
mov [esp],ebx
}
macro pushStringToStack x
{
sub esp,4
mov dword [esp],x
}
format PE console
entry start

include 'win32a.inc'

section '.text' code executable
start:
jmp enterNumber\$
enterNumber db "Enter a whole number (1 - 1'000'000).",10,0
enterNumber\$:
pushStringToStack enterNumber
call [printf]
pushPointerToStack original
jmp floatSign\$
floatSign db "%f",0
floatSign\$:
pushStringToStack floatSign
call [scanf]
jmp permutationString\$
permutationString db "The permutations of its digits are:",10,0
permutationString\$:
pushStringToStack permutationString
call [printf]
AsmEnd
numberOfDigits:=0
i:=0
While i<10
countDigits[i]:=0
i:=i+1
EndWhile
While original>0
numberOfDigits:= numberOfDigits + 1
lastDigit:= mod( original , 10 )
countDigits[ lastDigit ]:=countDigits( lastDigit ) + 1
original:= (original - lastDigit) / 10
EndWhile
AsmStart
if debug=1
AsmEnd
i:=0
While i<10
subscript:=4*i
AsmStart
fld dword [subscript]
fistp dword [subscript]
mov ebx,[subscript]
pushIntToStack (countDigits+ebx)
pushStringToStack integerSign
call [printf]
AsmEnd
i:=i+1
EndWhile
AsmStart
pushStringToStack newLineString
call [printf]
AsmEnd
AsmStart
end if
AsmEnd
topOfMyStack:=1
myStack[(numberOfDigits+1)]:=0
While topOfMyStack>0
currentNumberOfDigits:=myStack ( topOfMyStack * ( numberOfDigits + 1 ) )
i:=0
While i<currentNumberOfDigits
currentNumber(i):=myStack ( topOfMyStack * ( numberOfDigits + 1 ) + ( i + 1 ) )
i:=i+1
EndWhile
AsmStart
if debug=1
AsmEnd
i:=0
While i<currentNumberOfDigits
subscript:=i*4
AsmStart
fld dword [subscript]
fistp dword [subscript]
mov ebx,[subscript]
pushIntToStack (currentNumber+ebx)
pushStringToStack integerSign
call [printf]
AsmEnd
i:=i+1
EndWhile
AsmStart
pushStringToStack newLineString
call [printf]
AsmEnd
AsmStart
end if
AsmEnd
topOfMyStack:=topOfMyStack-1
If currentNumberOfDigits=numberOfDigits
i:=0
While i<numberOfDigits
subscript:=i*4
AsmStart
fld dword [subscript]
fistp dword [subscript]
mov ebx,[subscript]
pushIntToStack (currentNumber+ebx)
pushStringToStack integerSign
call [printf]
AsmEnd
i:=i+1
EndWhile
AsmStart
pushStringToStack newLineString
call [printf]
AsmEnd
Else
i:=0
While i<10
counter:=0
j:=0
While j<currentNumberOfDigits
If currentNumber(j)=i
counter:=counter+1
EndIf
j:=j+1
EndWhile
If counter<countDigits(i)
topOfMyStack:=topOfMyStack+1
myStack(topOfMyStack*(numberOfDigits+1)):=currentNumberOfDigits+1
j:=0
While j<currentNumberOfDigits
myStack(topOfMyStack*(numberOfDigits+1)+(j+1)):=currentNumber(j)
j:=j+1
EndWhile
myStack (topOfMyStack * (numberOfDigits + 1) + (j + 1) ) := i
EndIf
i:=i+1
EndWhile
EndIf
EndWhile
AsmStart
invoke system,_pause
invoke exit,0

_pause db "PAUSE",0
integerSign db "%d",0
newLineString db 10,0

original dd ?
result dd ?
lastDigit dd ?
numberOfDigits dd ?
countDigits dd 11 dup(?)
subscript dd ?
myStack dd 1000 dup(?)
topOfMyStack dd ?
counter dd ?
i dd ?
currentNumber dd 11 dup(?)
currentNumberOfDigits dd ?
j dd ?

library msvcrt,'msvcrt.dll'
import msvcrt,printf,'printf',system,'system',exit,'exit',scanf,'scanf'
AsmEnd    ```

The source code of the compiler, as well as the instructions on how to compile it and use it, can be downloaded here.
So, what do you think about it? Is it worth continuing developing it?
I am also dreaming about making my own LISP-like language, in which you will able to use both S-expressions and infix-expressions (since S-expressions come handy in array and string-manipulation, and infix-expressions come handy in arithmetic expressions), but I am unlikely to have time to develop it in foreseeable future.
05 Jan 2019, 17:48
Q9000

Joined: 16 Nov 2020
Posts: 1
Q9000
The actual website is down since a year or so but archive.org had at least picked the website up: https://web.archive.org/web/20191228041254/http://flatassembler.000webhostapp.com/compiler.html

It didn't save the actual program (.exe).
16 Nov 2020, 15:09
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First

 Jump to: Select a forum Official----------------AssemblyPeripheria General----------------MainTutorials and ExamplesDOSWindowsLinuxUnixMenuetOS Specific----------------MacroinstructionsOS ConstructionIDE DevelopmentProjects and IdeasNon-x86 architecturesHigh Level LanguagesProgramming Language DesignCompiler Internals Other----------------FeedbackHeapTest Area
Goto page Previous  1, 2

Forum Rules:
 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum