flat assembler
Message board for the users of flat assembler.

Index > Main > if in fool

Author
Thread Post new topic Reply to topic
edfed



Joined: 20 Feb 2006
Posts: 4237
Location: 2018
edfed
i will code a set of basic functions in fool

if, while, for, case...

and i meet the first problem.
how to code the CC?

if:
.call=0
.var1=4
.cc=8
.var2=12
.lbl0=16
.lbl1=20

if var1 cc var2 then lbl0
else lbl1

i will probably use a virtual flag register to don't depend on x86 arch.
e=0
ne=not 0
g=1
ng not 1
l=2
nl=not 2
etc etc...

then, how to assign a jcc to a cc? platform independant?
any idea?
Post 06 Sep 2008, 19:59
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
edfed wrote:
i will code a set of basic functions in fool
A set of basic functions in what? May be if you explain a bit...
Post 11 Sep 2008, 00:05
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 2891
Location: [RSP+8*5]
bitRAKE
edfed wrote:
then, how to assign a jcc to a cc? platform independant?
any idea?
LAHF/Jcc, or emit the opcodes - forcing other platforms to conform. Twisted Evil

Jump table based on CC - blah.

Bit set/get - usually only one is ever needed. Only update flags prior to use.

_________________
¯\(°_o)/¯ unlicense.org
Post 11 Sep 2008, 01:58
View user's profile Send private message Visit poster's website Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4237
Location: 2018
edfed
in fool ( fasm? fast? object oriented language)
a thing i "invented" because each time i coded something, it appeared clearlly that the graphical functions had always the same basic structure. FUNC,X,Y,XL,YL,COLOR

after, all normal functions had the same base, then, i wrote a set of functions, "easy to use", and object oriented.

objects are only datas structures.
theses objects have "always" the same base.

that's all.

for example, a if in this language is:
Code:
if:
.call=0
.op1=4
.cc=8
.op2=12
.then=16
.else=20 
;esi is the current item
;edi is hte parent item
        mov eax,[esi+.op1]
        mov ebx,[esi+.op2]
        mov ecx,[esi+.cc]
        cmp eax,ebx
        call get result
        push esi
        jc @f
        mov esi,[esi+.then]
@@:
        mov esi,[esi+.else]
        or esi,esi
        je .end
        mov eax,[esi+.call]
        or eax,eax
        je .end
        mov eax,[eax]
        je .end
        call eax
.end:
       pop esi
       ret

    


and how to use it:
Code:
main:
.if dd f.if,var1,equ,var2,way1,way2

way1 dd f.functionx,?,?,?,?,?,?,?,?,?
way2 dd 0
    

in this example, the if have only a single way.
if var1=var2, then, go in way1
else, do nothing.

this way, i can then code in asm, without asm, and close to asm.
but to be more hardcore, i want it multiplatform, but close to asm.

each object is a data structure, and then, an execution context for a function.

the problem is to code the CC to use for the fool, i think about a LUT
Post 11 Sep 2008, 20:39
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
edfed,

Looks like you're going to (re)invent something like direct threaded code in Forth (cute programming language by Charles Moore), or bytecode in Java™ (or even instruction set for your virtual CPU Wink). Of course, you'll need some kind of (almost inevitably) machine-dependent interpreter for such a code, but this is the other side of being platform-independent.

You will surely implement arithmetic operations, won't you? Then why do you have to constrain if's condition only to var1 CC var2? Implement additionally comparison and logical operations to evaluate some expression (even so simple as var1 = var2) to zero/non-zero result and pass it as a parameter to if.

Look-up table can be used (for example it can translate CC constants to jCC opcodes for IA-32 to use in self-modifying code), but being able only to compare two variables as a branch condition seems cumbersome and awkward.

Are f.functionx's parameters always passed by pointer (i.e. as an address, never a constant)?
Code:
        jc @f
        mov esi,[esi+.then]
@@:
        mov esi,[esi+.else]    
is not an if-then-else, is it?

By the way, mov eax, [eax] doesn't set flags...

Maybe you'll be interested to take a glance at Forth, IMHO it's as close to assembly as high-level language may come.
Post 19 Sep 2008, 17:50
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4237
Location: 2018
edfed
first, thanks for the positive feedback. ;D

about math operations, of course it is planed to do them.
as an input, the arithmetic formula, in ascii.
as output, the result, with a set of flags.
and finally, a branch, or a call, or nothing.

then, a formula will be pointed to by an address.
this formula will be a set of bytes.
all bytes will have an ascii value.
and the arithmetic parser will compute the formula.

for the moment, the formulas will be limited to 2 operands and 1 operation.

coding shall always start in the simplest form.

about the pointer, yes, it is always needed, but it is possibel to have constants.
for example, the code to draw a window in an application can be used in another application from the same pointer.
then, maybe a real data base access to object is the goal.
some speed never obtained in file manipulation.

famos is one of the OS to do the same thing, and reading it's site explains why it's better to do it in ram instead on disk.

but be carefull, fool is not so fool, it very powerfull and can destroy any system if you execute:
Code:
killhda:
dd f.disk
db disk.write,disk.hda
dw 65536
dd 0
dd cs:0  <-- to say it is in cs segment, mov ax,cs, mov [killhda+disk.segment],ax
dd 0
dd 0
    


oops, you show me a bug in the pseudo code i've posted.

Code:
jc .not
mov esi,[esi+.then]
jmp @f
.not:
mov esi,[esi+.else]
@@:
mov eax,[esi]
mov eax,[eax]
call eax
    


effectivelly, it was not a if then else.

but about if, i've tryed it, and constated it is hard to make it as easy as pure asm.

cmp reg,[mem]
cmp reg,const
cmp [mem],const
cmp reg,reg
cmp [mem],[mem]
cmp [[mem]],[reg]

etc,etc...
Post 19 Sep 2008, 21:10
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
edfed,

I've meant this:
Code:
;...
check_for_intruder:
        dd      f.sub, object.x, base.x, diff.x
        dd      f.sub, object.y, base.y, diff.y
        dd      f.mul, diff.x, diff.x, diff_x_squared
        dd      f.mul, diff.y, diff.y, diff_y_squared
        dd      f.add, diff_x_squared, diff_y_squared, distance_squared
        dd      f.cmp_le, distance_squared, literal_100, object_is_near_base
        dd      f.cmp_eq, object.color, literal_color_red, object_is_red
        dd      f.boolean_and, object_is_near, object_is_red, red_object_is_near_base
        dd      f.if, red_object_is_near_base, red_alert, all_your_base_are_belong_to_us
;...
red_alert:
        dd      f.zap, object, literal_immense_power
        dd      f.say, literal_favorite_phrase
;...
all_your_base_are_belong_to_us:
        dd      f.stomp, area_around
;...
literal_100     dd      100
literal_immense_power   dd      666
literal_favorite_phrase db      "Was that you, John Wayne?", 0    
Calculate logical expression ((object.x-base.x)²+(object.y-base.y)²) <= 100 & object.color=red, pass the boolean result to if... Wink

The big question is: why do you need this? Additional layer over raw machine code must be thin and transparent, or else you probably will end up with something like HLA (Randall did a good effort in structuring inherently "spaghetty-code" assembly language and his "Art of Assembly Language" is awesome).

But I beg to differ: I'm in assembly language programming for raw and sheer power it gives. Here is the example (the idea was simple, but it tooks me around an hour to cast it in metal):
Code:
                format  PE GUI
                include "WIN32A.INC"

                section ".code" code executable readable writeable
                entry   $
                mov     esp, wicked_stack
MessageBox:     jmp     [__imp__MessageBoxA@16]
ExitProcess:    jmp     [__imp__ExitProcess@4]

eax_eq_literal?_branch:
                cmp     eax, [esp]
                pop     eax
                pop     eax
                jnz     @f
                mov     esp, eax
@@:             ret

                rb      65536

                section ".data" data readable writeable
wicked_stack:
                dd      MessageBox
                dd      HWND_DESKTOP, hello_world, hello_caption, MB_OK+MB_ICONEXCLAMATION
                dd      eax_eq_literal?_branch
                dd      HWND_DESKTOP, goodbye_world, hello_caption, MB_YESNO+MB_ICONQUESTION
                dd      IDYES, goodbye_ok
                dd      MessageBox
                dd      ExitProcess
                dd      HWND_DESKTOP, goto_hell_world, hello_caption, MB_OK+MB_ICONINFORMATION
                dd      0
                dd      -1
goodbye_ok:     dd      ExitProcess
                dd      0
                dd      0

hello_caption   db      "Wicked Hello", 0
hello_world     db      "Hello, World!", 0
goodbye_world   db      "Goodbye, World?", 0
goto_hell_world db      "Go to hell, cruel World!", 0

                data    import
                library USER32, "USER32.DLL",\
                        KERNEL32, "KERNEL32.DLL"
                import  USER32,\
                        __imp__MessageBoxA@16, "MessageBoxA"
                import  KERNEL32,\
                        __imp__ExitProcess@4, "ExitProcess"
                end     data    
Neat, heh? Obscure enough, but some macros will ease the pain.

Especially I like that MessageBox function returns from the first "call" (jmp to be correct) right to itself's start (recursion? no, stack flow control Wink).

eax_eq_literal?_branch function demonstrates conditional jump after comparison (eax==parameter).

The great flaw of this example is that flow-controlling data on stack is literally obliterated Wink by OS calls (why do OS use my stack for it's dirty tricks, only to simplify it's code?), so only forward branch (and rb 65536 to satisfy Windows hunger for stack).
Post 20 Sep 2008, 12:05
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4237
Location: 2018
edfed
Quote:

Calculate logical expression ((object.x-base.x)²+(object.y-base.y)²) <= 100 & object.color=red, pass the boolean result to if...

The big question is: why do you need this?


i don't need this, nobody needs any computer, just human being want it to work.

for me, fool is just a way to don't have to do multiples mov's or push's each time i call a function.
as a result, it gives a language.

about the function to do the if:
Code:
                dd f.if, expression,condition,way1,way2
expression db '((object.x-base.x)²+(object.y-base.y)²) <= 100 & [object.color]=red',0
condition dd true
way1         dd f.x,?,?,?
way2         dd f.x,?,?,?
    


coding expression directlly in ascii seems to be a good thing.
Post 21 Sep 2008, 07:21
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
edfed wrote:

i don't need this, nobody needs any computer, just human being want it to work.
Smile I got your point. The question was somewhat out of context.

Is it only parameters' passing conventions that you don't like? If so, maybe you take a look at Forth? I'm not pushing you in any way... Wink

The IA-32 is somewhat constraining regarding to general-purpose registers (we can easily have 1-2-3-4 GB of relatively slow RAM and sink it through so small number of fast registers? Not to mention cache coherency and other issues with multi-CPU systems). Is it so difficult to have several hundreds of registers? Locally code uses only small portion of them, I think four base pointers to big registers' file plus 2..3-bit index will be enough to have four objects (in wide sense) to manipulate their properties without access to RAM.

CPUs have to be designed by their programmers, period. Wink
When the authors of the game's rules don't play it (or don't have to abide by them)…

My hopes toward Intel® 64 architecture was gone with the wind.

Sorry for this rant.
Post 21 Sep 2008, 11:45
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17248
Location: In your JS exploiting you and your system
revolution
baldr wrote:
Is it so difficult to have several hundreds of registers?
Actually it is, yes. It is not difficult to actually provide the registers, it is difficult to access the registers. Because it means the entire instruction set needs to have multiple bits available to fully identify which of the hundreds of registers one wants to use. An example of that is the Itanium. It has 128/128 registers (128 integer + 128 floating point). The instruction set was completely redesigned to accommodate it.
Post 21 Sep 2008, 12:02
View user's profile Send private message Visit poster's website Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4237
Location: 2018
edfed
there, we see the lack of adatative comportment from IA arch designers.
why don't use all the existing instruction set, and say, in hardware, address space from xxxxx to yyyyy is not related to memory, but registers.
and with this, mov [reg],value will act as a very fast memory operation...
it willl be pb, how to code mov [ezx],[ekx]?
Post 21 Sep 2008, 12:13
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr
revolution wrote:
It is not difficult to actually provide the registers, it is difficult to access the registers. Because it means the entire instruction set needs to have multiple bits available to fully identify which of the hundreds of registers one wants to use.
Just to make it clear:
baldr wrote:
Locally code uses only small portion of them, I think four base pointers to big registers' file plus 2..3-bit index will be enough to have four objects (in wide sense) to manipulate their properties without access to RAM.
That is, 4..5 bits for register addressing mode. However, with that access method you can't address entire registers' file at once, but do you really need it? Registers are only the temporary storage, aren't they? If you need direct access to 128 temporary variables... isn't it a sign of problem in your code?
Post 22 Sep 2008, 05:54
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar.

Powered by rwasa.