flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > New .if/.else/.loop Approach

Author
Thread Post new topic Reply to topic
uart777



Joined: 17 Jan 2012
Posts: 369
uart777
Hi. Just wanted to share my unique variations of .if/.else
and loops. I thought programmers might be interested in
seeing a different approach.

FASM's version of .if is much more advanced, but this one
is simpler and results in faster assembly processing.

Have fun!

Code:

; $$$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$
; *************** SUNGOD SOFTWARE ****************
; ??????????????????? IF.INC ?????????????????????

!NOT equ 0

; jump if condition to l (or !NOT if 1)

macro JIF l, [c] {
common
local s
define s 0
macro J O,A,C,B, [X] \{
match =0 X, s c \\{
  O A, B ; opcode o1, o2
  if !NOT eq 0
    j\#C l
  else
    jN\#C l
  end if
  define s 1
\\}
\}
J cmp,a,LE,b, a<==b    ; a<=b
J cmp,a,GE,b, a>==b    ; a>=b
J cmp,a,L,b, a<b       ; a<b
J cmp,a,G,b, a>b       ; a>b
J cmp,a,E,b, a==b      ; a=b
J cmp,a,NE,b, a =not b ; a not b (unequal)
J test,a,NE,b, a&b     ; a&b
J or,a,NE,b, a|b       ; a|b
J cmp,a,E,0, =not a    ; not a (=0)
J cmp,a,NE,0, a        ; a (not 0)
if s eq 0
ERROR: 'Invalid expression'
end if
purge J
}

; jump if NOT condition to l

macro JIFN l, [c] {
common
!NOT equ 1
JIF l, c
!NOT equ 0 ; restore default
}

; HL IF/ELSE

macro .if.begin {
local ..start, ..else, ..end
?IF equ
?START equ ..start
?ELSE equ ..else
?END equ ..end
?START:
}

macro .if [c] {
common
.if.begin
JIFN ?ELSE, c ; if false, jmp to end
}

macro .if.n [c] {
common
.if.begin
JIF ?ELSE, c
}

macro .else {
jmp ?END
?ELSE:
restore ?IF
?IF equ ,
}

macro .else.if [c] {
common
jmp ?END
?ELSE:
restore ?ELSE
local ..else
?ELSE equ ..else
JIFN ?ELSE, c
}

macro .end {
if ?IF eq
?ELSE:
end if
?END:
restore ?IF, ?START, ?ELSE, ?END
}

jNE equ jne
jNNE equ je
jNG equ jng
jNL equ jnl

; $$$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$
; *************** SUNGOD SOFTWARE ****************
; ?????????????????? LOOP.INC ????????????????????

; .loop i=x to n
; .endl

; .while a<b
; .endw

; .until a=b
; .endu

; .continue
; .break

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

macro .loop [c] {
local ..start, ..end
?START equ ..start
?END equ ..end
define ?s 0
match i==x =to n, c \{
define ?s 1
?INDEX equ i
push x ; let i=x
pop i
?START:
mov ecx, i
cmp ecx, n
jge ?END
\}
if ?s eq 0
ERROR: 'Incorrect loop syntax'
end if
}

macro .endl {
inc ?INDEX    ; i++
jmp ?START    ; continue
?END:
restore ?START, ?END, ?INDEX
}

macro .while [c] {
common
.if c
}

macro .endw {
jmp ?START
.end
}

macro .until [c] {
common
.if.n c
}

.endu fix .endw

macro .continue { jmp ?START }
macro .break { jmp ?END }    


Last edited by uart777 on 18 Jan 2012, 16:39; edited 1 time in total
Post 17 Jan 2012, 23:38
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1281
Location: countryside
Picnic
Hi uart777,

Can you give a usage example of .loop macro because i'm having an illegal instruction error.
Post 18 Jan 2012, 12:35
View user's profile Send private message Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369
uart777
Oh, sorry. Edited. Replaced let i=x with push x, pop i. It was written this way to support all memory operands as in: .loop [a]=[b] to [c]

; an example with my code...

include 'z.inc'

integer i=0
text t(32), f='Value: %n/%hh/%bb'

code
.loop [i]=0 to 3
print t, f, [i], [i], [i]
MessageBoxA 0, t, t, 0 ; no invoke needed with my code Wink
.endl ; < remember, .endl for .loop
exit
Post 18 Jan 2012, 16:22
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1281
Location: countryside
Picnic
Well it's nice. Smile
I did a small modification tο adjust the loop counter properly.

Code:
macro .loop [c] {
    local ..start, ..end
    define ?s 0
    match i==x =to n, c \{
        define ?s 1
        push x ; let i=x
        pop i
        ..start:
       ?START equ ..start
          ?END equ ..end        
        ?INDEX equ i
        ?LIMIT equ n
    \}
    if ?s eq 0
        ERROR: 'Incorrect loop syntax'
    end if
}

macro .endl {
    mov ecx, ?INDEX
    cmp ecx, ?LIMIT
    je ?END
    inc ?INDEX    ; i++
    jmp ?START    ; continue
    ?END:
    restore ?START, ?END, ?INDEX, ?LIMIT
}
    
Post 19 Jan 2012, 00:05
View user's profile Send private message Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369
uart777
Thanks. Nothing is wrong with the index/counter. I have tested .if/.else/.loop extensively, even used them to create useful programs like art/image editors and mini dis/assemblers.

However, I just noticed that .break and .continue do NOT WORK properly. They jmp to the beginning or end of ANY recent HL block including if.

To correct this, each HL block must have a distinctive begin and end (?BEGIN.IF, ?BEGIN.LOOP, etc) or there must be separate versions of break/continue (.breakl, .breakw). Otherwise, something like this will not work:

.loop [i]=0 to [variables.n]
array.index variables, [i]
let eax=&[?variable.name+eax]
.if.text.equal [token], eax
.break ; error: jmps to .if start, not .loop
jmp @f ; < use this instead
.end
.endl
@@:
Post 24 Jan 2012, 03:24
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1281
Location: countryside
Picnic
uart777 wrote:
Thanks. Nothing is wrong with the index/counter. I have tested .if/.else/.loop extensively, even used them to create useful programs like art/image editors and mini dis/assemblers.


Oh, forgive my carelessness uart777. It was late at night. Smile
Post 24 Jan 2012, 07:13
View user's profile Send private message Reply with quote
Overflowz



Joined: 03 Sep 2010
Posts: 1046
Overflowz
Hi uart777, I'm not fimilar with macro and can you post that macro, where we can use API calls without invoke ? Thank you.
Post 24 Jan 2012, 11:19
View user's profile Send private message Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369
uart777
Hi, Overflowz. I have custom "library; import" macros that construct
the PE import table manually (db x) and define the name itself as a
macro which calls it from the ITA. Thus, no "invoke"-like prefix and
automatic error checking on number of parameters. To understand
this, check out my command/"proc/edure" file:

Code:
; $$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$$
; ************** SUNGOD SOFTWARE *****************
; ???????????????? COMMAND.INC ???????????????????

; push parameters forwards or backwards

macro pushf [p] { ; push parameters forward
common if ~ p eq
forward pushd p
common end if
}

macro pushr [p] { ; push parameters backwards
common            ; to access forwards
if ~p eq
reverse pushd p
common
end if
}

; call a/ddress direct or p/ointer indirect

macro calla a, [p] {
common pushr p
call a
}

macro callp c, [p] { common calla [c], p }

; call direct with "variable arguments" (...)
; then push invisible # parameters last
; (TEXT>print t, f, ... uses this convention)

macro callv c, [p] {
common ?n=1
reverse pushd p
?n=?n+1
common push ?n
call c
add esp, ?n*4
}

; call cdecl direct (or indirect if [c])

macro cdecl c, [p] {
common ?n=0
reverse pushd p
?n=?n+1
common
call c
add esp, ?n*4
}

; call DirectX "interface"

macro callx c, x, [p] {
common
pushr p            ; push parameters
mov eax, [c]
push eax           ; push class address
mov eax, [eax]
call dword [eax+x] ; call c+m
}

macro callfp f { ; call function pointer
cmp dword [f], 0 ; if defined
jz @f
calla dword [f]
@@:
}

;;;;;;;;;;;;;;;;;;;; COMMAND ;;;;;;;;;;;;;;;;;;;;

; create "function/proc/edure"

macro command name, [p] {
common

; only insert this inside of the executable
; if it was used somewhere

if used !#name
!#name: ; real command !name

; macro to call with no callp/"invoke" prefix.
; example: f a, b, c

macro name p \{
pushr p
call !#name
\}

!#name.$type='c'
?begin equ !#name
?parameters equ p
..n.parameters=0
..n.locals=0
..locals.size=0

; create parameter names and offsets

if ~ p eq          ; if parameters
  virtual at ebp+8
  forward
  local ..p
  ..p dd ?         ; (ebp+Cool+i*4
  p equ ..p
  ..n.parameters=..n.parameters+1
  common
  end virtual
  push ebp         ; create stack frame
  mov ebp, esp
end if
; ...
}

; HL return statement. use this instead of
; ret/n in HL commands. no ret/urn before endc.
; it inserts one automatically

macro return v {
common
if ~ v eq ; value?
  mov eax, v
end if
if ..n.parameters<>0   ; if parameters
  leave
  ret ..n.parameters*4 ; ret n
else if ..n.locals<>0  ; if locals
  leave
  ret
else
  ret
end if
}

; end command

macro endc {
return
.$=$-?begin ; total size
if ..n.parameters<>0 ; if parameters
  match p, ?parameters \{ restore p, ?begin \}
end if
if ..n.locals<>0 ; if locals
  match l, local.names \{ restore l \}
end if
; ...
end if ; end "if used name" at very beginning
}

; locals ... - create local 32BIT variables.
; example: locals x, y, n, c

macro locals [p] {
common local.names equ p
forward ..n.locals=..n.locals+1
common ..locals.size=..n.locals*4
virtual at ebp-..locals.size
forward
local ..l
..l dd ?
p equ ..l
common
end virtual
if ..n.parameters=0
push ebp ; create stack frame
mov ebp, esp
end if
sub esp, ..locals.size ; "allocate" locals
}

; localz ... - same but initialize locals;
; for local pointers that re/allocate
; memory or structures that should have
; 0/default values

macro localz [p] {
common
locals p
push edi
mov edi, esp
xor eax, eax
mov ecx, (..locals.size shr 2)
rep stosd
pop edi
}
    


Example usage:

Code:
; draw "bitmap"; 2D pixel array

command draw.bitmap, pixels, x, y, w, h, key, alpha
locals p, i, iw
visible [x], [y], [w], [h]  ; invisible? return
fail .r
let eax=[pixels], [p]=eax,\ ; p=pixels
ecx=[w], ecx<<2, [iw]=ecx   ; image w in bytes
.loop [i]=0 to [h]
  let eax=[y], eax+[i]
  draw.scanline [p], [x], eax, [w],\
  [key], [alpha]
  let eax=[iw], [p]+eax
.endl
.r:
endc
    


Now, to call this, just write its name and parameters (no
"invoke"-like prefix):

draw.bitmap [p], [x], [y], [w], [h], [key], [alpha]

- SUNGOD SOFTWARE
Post 25 Jan 2012, 04:58
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-2019, Tomasz Grysztar.

Powered by rwasa.