Message board for the users of flat assembler.
> Main > if in fool
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 var1 cc var2 then lbl0
i will probably use a virtual flag register to don't depend on x86 arch.
ng not 1
then, how to assign a jcc to a cc? platform independant?
|06 Sep 2008, 19:59||
A set of basic functions in what? May be if you explain a bit...
i will code a set of basic functions in fool
|11 Sep 2008, 00:05||
LAHF/Jcc, or emit the opcodes - forcing other platforms to conform.
then, how to assign a jcc to a cc? platform independant?
Jump table based on CC - blah.
Bit set/get - usually only one is ever needed. Only update flags prior to use.
|11 Sep 2008, 01:58||
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.
for example, a if in this language is:
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:
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
|11 Sep 2008, 20:39||
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 ). 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)?
is not an if-then-else, is it?
jc @f mov esi,[esi+.then] @@: mov esi,[esi+.else]
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.
|19 Sep 2008, 17:50||
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:
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.
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.
|19 Sep 2008, 21:10||
I've meant this:
Calculate logical expression ((object.x-base.x)²+(object.y-base.y)²) <= 100 & object.color=red, pass the boolean result to if...
;... 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
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):
Neat, heh? Obscure enough, but some macros will ease the pain.
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
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 ).
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 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).
|20 Sep 2008, 12:05||
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:
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.
|21 Sep 2008, 07:21||
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...
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.
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.
|21 Sep 2008, 11:45||
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.
Is it so difficult to have several hundreds of registers?
|21 Sep 2008, 12:02||
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]?
|21 Sep 2008, 12:13||
Just to make it clear:
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.
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?
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.
|22 Sep 2008, 05:54||
< Last Thread | Next Thread >
Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.
Website powered by rwasa.