Logo Search packages:      
Sourcecode: sbm version File versions  Download package

helptool.h

%ifndef _help_tool_inc
%define _help_tool_inc

; this file define the help macros for the nasm assembers. Using those macros
; can moduler program in the assember, do not need to jmp any more.
;                                   --have fun!!
; 
; Copyright 2000 Christopher Li <chrisl@turbolinux.com.cn>
; 

%assign __cont__ 0
%assign __break__ 0
%assign __return__ 0
%assign __level__ 0
%assign __cndblock__ 0
%macro cat_define 3
%define %{1}%{2} %{3}
%endmacro

%macro l_define 4
%define %{1}%{2} %{3}%{4}
%endmacro

%macro cat_undef 3
%undef %{1}%{2}%{3}
%endmacro

%macro cat_lable 2
%{1}%{2}:
%endmacro

%macro linecat 3
      %1 %{2}%{3}
%endmacro

%macro cat_jc 3
      j%+1 %{2}%{3}
%endmacro

%macro cat_jnc 3
      j%-1 %{2}%{3}
%endmacro

%macro cat_jc_near 3
      j%+1 near %{2}%{3}
%endmacro

%macro cat_jnc_near 3
      j%-1 near %{2}%{3}
%endmacro


%macro cat_jmp 2
      jmp short %{1}%{2}
%endmacro

%macro cat_jmp_near 2
      jmp near %{1}%{2}
%endmacro

%macro jmp_near 2
      %if %1 > 0
            jmp near %2
      %else
            jmp short %2
      %endif
%endmacro

%macro con_push 1
      %assign __lastlevel__ __level__
      %assign __level__ __level__ + 1
      %if __return__ > 0
            %assign con_return 1
      %else
            %assign con_return 0
      %endif

      %if __cont__ > 0
            %assign con_cont 1
      %else
            %assign con_cont 0
      %endif
      %if __break__ > 0
            %assign con_break 1
      %else
            %assign con_break 0
      %endif
; if the contex are going to provide the lable, then we don't provide it twice.
      %ifidn %1,proc
            %assign con_return 0
      %elifidn %1,forcx
            %assign con_break 0
      %elifidn %1,repeat
            %assign con_cont 0
            %assign con_break 0
      %elifidn %1,while
            %assign con_cont 0
            %assign con_break 0
      %endif

      %if __cndblock__ == 1
          l_define %$ifnot,__lastlevel__,%$ifnot,{}
      %endif

      %push %1
      %if con_return
          l_define %$return,__level__,%$$return,__lastlevel__
      %endif
      %if con_break
          l_define %$break,__level__,%$$break,__lastlevel__
      %endif
      %if con_cont
          l_define %$cont,__level__,%$$cont,__lastlevel__
      %endif
      
      %ifidn %1,andblock
          l_define %$ifnot,__level__,%$$ifnot,__lastlevel__
      %elifidn %1,orblock
          l_define %$ifnot,__level__,%$$ifnot,__lastlevel__
      %endif      
%endmacro

%macro con_pop 0
      %pop
      %assign __level__ __level__ - 1
%endmacro

%macro proc 1-*
GLOBAL %{1}
%{1}:
con_push proc
%assign  __return__ __return__ + 1
%assign __have_frame__ 0
%assign %$have_local 0
%assign %$have_save  0
%assign __save_all__ 0
%assign %$local_args 0
%assign %$proc_args 0
%assign __save_args__ 0
%if %0 > 1
      %assign args %0 - 1
      %assign %$bp_off 4
      %assign i 0
      %rotate 1
      %ifidn %1,withlocal
            %assign %$have_local 1
            %assign args args -1
            %rotate 1
      %endif 
      %assign %$proc_args args
      %rep args
            ; define the args
            %%inputarg__%{1} EQU %$bp_off
            %undef .%1
            %define .%{1} %%inputarg__%{1}+bp
            cat_define %$proc_argv ,i,%1 
            %assign %$bp_off %$bp_off + 2
            %assign i i+1
            %rotate 1
      %endrep
      %if %$have_local==0
            enter 0,0
            %assign __have_frame__ 1
      %endif
%endif
%endmacro

%macro local 0-*
%ifctx proc
      %if %$have_local == 1
            %assign argc %0
            %assign local_vars 0
            %assign %$have_local 2
            %assign local_off 0
            
            %assign i 0
            %rep argc
                  %ifnum %2
                        %assign local_off local_off+%2
                        %assign token_eat 2
                  %else
                        %assign local_off local_off+2
                        %assign token_eat 1
                  %endif

                  %%local__%{1} EQU local_off
                  %undef .%{1}
                  %define .%{1} bp-%%local__%{1}
                  cat_define %$proc_argv ,i,%1 
                  %assign argc argc-token_eat
                  %if argc <= 0
                        %exitrep
                  %endif
                  %assign i i+1
                  %rotate token_eat
            %endrep
            %assign %$local_args i
            enter local_off,0
            %assign __have_frame__ 1
      %else
            %error "`proc' not declear `withlocal' as the first argument"
      %endif
%else
      %error "expected `proc' before `local'"
%endif
%endmacro

%macro invoke 1-*
      %if %0 == 2
          push word %1
          %assign rargc 1               
      %else
      %rotate -2
      %assign argc %0-1
      %assign rargc 0
      %rep argc
          %ifidn %1,byte
            push byte %2
            %rotate -1
            %assign argc argc -1
            %assign rargc rargc +1
          %elifidn %1,word
            push word %2
            %rotate -1
            %assign argc argc -1
            %assign rargc rargc +1
          %elifidn %1,dword
              push dword %2
            %rotate -1
            %assign argc argc -1
            %assign rargc rargc +2
          %else
              push word %2
            %assign rargc rargc +1
          %endif
          %rotate -1
          %assign argc argc -1
          %if argc <=0 
            %exitrep
          %endif
      %endrep
      %rotate 1
      %endif
      call %1
      add sp,(rargc)*2
%endmacro

%macro save 1-*
%ifctx proc
      %if %$have_local == 1
            %error "`save' must after `local'"
      %endif

      %ifidn all,%1
            %assign __save_all__ 1
            %if %0 > 1
                  %ifidn frame,%2
                        %if __have_frame__ == 0
                              enter 0,0
                              %assign __have_frame__ 1
                              %assign local_off 0
                        %endif
                  %endif
            %endif
            pusha
            %if __have_frame__ == 1
                  %undef __AX
                  %undef __BX
                  %undef __CX
                  %undef __DX
                  %undef __SI
                  %undef __DI
                  %idefine __AX bp-local_off - 2
                  %idefine __CX bp-local_off - 4
                  %idefine __DX bp-local_off - 6
                  %idefine __BX bp-local_off - 8
                  ; %idefine __SP bp-local_off - 10
                  ; %idefine __BP bp-local_off - 12
                  %idefine __SI bp-local_off - 14
                  %idefine __DI bp-local_off - 16
            %endif
      %elifidn alld,%1
            %assign __save_all__ 2
            %if %0 > 1
                  %ifidn frame,%2
                        %if __have_frame__ == 0
                              enter 0,0
                              %assign __have_frame__ 1
                              %assign local_off 0
                        %endif
                  %endif
            %endif
            pushad
            %if __have_frame__ == 1
                  %undef __EAX
                  %undef __EBX
                  %undef __ECX
                  %undef __EDX
                  %undef __ESI
                  %undef __EDI
                  %idefine __EAX bp-local_off - 4
                  %idefine __ECX bp-local_off - 8
                  %idefine __EDX bp-local_off - 12
                  %idefine __EBX bp-local_off - 16
                  ; %idefine __SP bp-local_off - 10
                  ; %idefine __BP bp-local_off - 12
                  %idefine __ESI bp-local_off - 18
                  %idefine __EDI bp-local_off - 32
            %endif

      %else
            %assign __save_args__ %0
            %assign __save_all__ 0
            %assign i %0
            %rep %0
                  push %1
                  cat_define %$save_argv ,i,%1 
                  %rotate 1
                  %assign i i - 1
            %endrep
      %endif
%else
      %error "`save' must after `proc'"
%endif
%endmacro

%macro endp 0-1
%ifnctx proc
      %error "expected `proc' before `endp'"
%endif
      cat_lable %$return,__level__
      %if __save_all__ ==1 
            popa
      %elif __save_all__ == 2
            popad
      %elif __save_args__ > 0
            %assign i 1
            %rep __save_args__
                  linecat pop, %$save_argv,i
                  %assign i i+1
            %endrep
      %endif
      %if __have_frame__ > 0
          leave
      %endif
      ; cleanup proc_args
      %assign i 0
      %rep %$proc_args
;           %undef %$proc_argv1
            %assign i i+1
      %endrep
      ; cleanup local_args
      %assign i 0
      %rep %$local_args
;           cat_undef %$local_argv,i
            %assign i i+1
      %endrep
      ret
      con_pop
      %assign  __return__ __return__ - 1
%endmacro

%macro mov_ax 1
      %if %1 == 0
            sub ax,ax
      %else
            mov ax,%1
      %endif
%endmacro

%macro return 0-*
    %if %0 > 0
      %assign __near__ 0
      %assign argc %0
      %ifidn %1,near
            %assign __near__ 1
            %assign argc argc-1
            %rotate 1
      %endif
      %if argc > 0
      %ifidn %1,if
          ; return if, {cmp ax, 0},e 
          %rotate 1
          %rep argc-2
            %1
            %rotate 1
          %endrep
          %if __near__ == 0
            cat_jc %1,%$return,__level__
          %else
            cat_jc_near %1,%$return,__level__
          %endif  
      %else
          %error "expect `if' after `return'"
      %endif
      %else
      %if __near__ == 0
            cat_jmp %$return,__level__
      %else
            cat_jmp_near %$return,__level__
      %endif
      %endif
    %else
      %if __have_frame__ == 0 && __save_all__ == 0 && __save_args__ == 0
            ret
      %else 
            cat_jmp %$return,__level__
      %endif      
    %endif
%endmacro



%macro forcx 0-1
con_push forcx
%assign  __break__ __break__ + 1
%if %0 > 0
      mov   cx, %1
%endif
%$begin:
%endmacro

%macro endforcx 0-*
    %ifnctx forcx
      %error "expected `forcx' before `endfor'"
    %endif
      %if %0 > 0
          %ifidn %1,while
            %rotate 1
            cat_lable %$cont,__level__
            %rep %0 - 2
                  %1
                  %rotate 1
            %endrep
          %else
            %error "expected `while' after `endfor'"
          %endif
            loop%+1 %$begin
      %else
          loop %$begin
      %endif
      %$end:
      cat_lable %$break,__level__
      
      con_pop
      %assign  __break__ __break__ - 1
%endmacro

; forcx 5, e
;     mov cx,ax
;     cmp ax,bx
; endfor 
;

%macro repeat 0
con_push repeat
%assign  __break__ __break__ + 1
%assign  __cont__ __cont__ + 1
%$begin:
cat_lable %$cont,__level__
%endmacro

%macro until 1-*
    %assign __near__ 0
    %assign __argc__ %0
    %ifidn near,%1
      %assign __near__ 1
      %rotate 1
      %assign __argc__ __argc__ -1
    %endif  
    %rep __argc__ -1
      %1
      %rotate 1
    %endrep
    %ifctx repeat
      %if __near__ >0
            j%-1 near %$begin
      %else
              j%-1 %$begin
      %endif
      %$end:
      cat_lable %$break,__level__
    %else
      %error "expected `repeat' before `until'"
    %endif
con_pop
%assign  __break__ __break__ - 1
%assign  __cont__ __cont__ - 1
%endmacro

; repeat
;     mov cx,ax
;     cmp ax,bx
; until e
;

%macro while 0-*
con_push while
%assign  __break__ __break__ + 1
%assign  __cont__ __cont__ + 1
%$begin:
cat_lable %$cont,__level__
%if %0 > 0
    %rep %0 -1
      %1
      %rotate 1
    %endrep
    j%-1 %$end
%endif
%endmacro

%macro endwhile 0
    %ifctx while
          jmp %$begin
        %$end:
        cat_lable %$break,__level__
    %else
      %error "expected `while' before `endwhile'"
    %endif
con_pop
%assign  __break__ __break__ + 1
%assign  __cont__ __cont__ + 1
%endmacro

; while {cmp ax, bx}, e
;   mov ax, cx
; endwhile

%macro break 0-*
%if %0 > 0
      %ifidn %1,if
          %rotate 1
          %rep %0 - 2
          %1
          %rotate 1
          %endrep
          cat_jc %1,%$break,__level__
      %else
          %error "expect `if' after `break'"
      %endif
%else
      cat_jmp %$break,__level__
%endif
%endmacro

%macro continue 0-*
%if %0 > 0
      %ifidn %1,if
          %rotate 1
          %rep %0 - 2
          %1
          %rotate 1
          %endrep
          cat_jc %1,%$cont,__level__
      %else
          %error "expect `if' after `continue'"
      %endif
%else
      cat_jmp %$cont,__level__
%endif
%endmacro

%macro goto 1-*
%if %0 > 1
      %ifidn %2,if
          %rotate 1
          %rep %0 - 3
            %2
            %rotate 1
          %endrep
          %rotate 1
          j%+1 %2
      %else
          %error "expect `if' after `continue'"
      %endif
%else
      jmp %1
%endif
%endmacro

%macro goton 1-*
%if %0 > 1
      %ifidn %2,if
          %rotate 1
          %rep %0 - 3
            %2
            %rotate 1
          %endrep
          %rotate 1
          j%+1 NEAR %2
      %else
          %error "expect `if' after `continue'"
      %endif
%else
      jmp %1
%endif
%endmacro

%macro if 0-*
    %rep %0 -1
      %1
      %rotate 1
    %endrep

    con_push if

    %if %0 > 0
      j%-1 %$ifnot
    %endif
    %assign %$elif_level 0
%endmacro


%macro andblock 0
      %assign __cndblock__ __cndblock__ + 1
      con_push andblock
%endmacro

%macro orblock 0
      %assign __cndblock__ __cndblock__ + 1
      con_push orblock
%endmacro

%macro endblock 0-1
      %ifctx orblock
            cat_jmp %$ifnot,__level__
            %$iftrue:
      %elifctx andblock
      %else
            %error "not in andblock or orblock"
      %endif
      con_pop
      %assign __cndblock__ __cndblock__ - 1
%endmacro

%macro condiction 1-*
      %rep %0 -1
            %1
            %rotate 1
      %endrep
      %ifctx andblock
            cat_jnc %1,%$ifnot,__level__
      %elifctx orblock
            j%+1 %$iftrue
      %else
            %error "not in the andblock or orblock"
      %endif
%endmacro

%macro else 0-1
    %assign __near__ 0
    %if %0 >0
      %ifidn %1 near
            %assign __near__ 1
      %endif
    %endif
    %ifctx if
        %repl else
        jmp_near __near__,%$ifend
        %$ifnot:
    %elifctx elif
;     %assign elselevel %$elif_level - 1
      jmp_near __near__,%$ifend
      %$ifnot:
      %repl else
      
;     con_pop
;     %rep elselevel
;           %$ifend:
;           con_pop
;     %endrep
    %else
        %error "expected `if' before `else'"
    %endif
%endmacro

%macro elif 1-*
      %ifctx elif
            %assign level %$elif_level + 1
      %else 
            %assign level 1
      %endif
      %repl else
      jmp %$ifend
      %$ifnot:
      %rep %0 -1
            %1
            %rotate 1
      %endrep
      con_push elif
      j%-1 %$ifnot
      %assign %$elif_level level
%endmacro

%macro endif 0
    %assign elselevel 0
    %ifctx if
        %$ifnot:
        con_pop
    %elifctx else
        %assign elselevel %$elif_level
        %$ifend:
        con_pop
    %elifctx elif
      %assign elselevel %$elif_level
      %$ifnot:
      con_pop
    %else
        %error "expected `if' or `else' before `endif'"
    %endif
      %rep elselevel
            %$ifend:
            con_pop
      %endrep
%endmacro
;          cmp ax,bx
;          if ae
;            cmp bx,cx
;            if ae
;              mov ax,cx
;            else
;              mov ax,bx
;            endif
;          else
;            cmp ax,cx
;            if ae
;              mov ax,cx
;            endif
;          endif

%push __base__
%endif

Generated by  Doxygen 1.6.0   Back to index