New upstream version 2.0pre9.2
This commit is contained in:
304
test/ecm/lmacros/jn_warn.mac
Normal file
304
test/ecm/lmacros/jn_warn.mac
Normal file
@@ -0,0 +1,304 @@
|
||||
[list -]
|
||||
%if 0
|
||||
|
||||
Warn for near jumps
|
||||
Public Domain by C. Masloch, 2018
|
||||
|
||||
%endif
|
||||
|
||||
%ifndef __JN_WARN_MAC__
|
||||
%assign __JN_WARN_MAC__ 1
|
||||
|
||||
%imacro jz 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jnz 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro je 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jne 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jc 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jnc 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jb 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jnb 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro ja 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jna 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jae 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jnae 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jbe 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jnbe 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
%imacro js 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jns 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%imacro jo 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jno 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%imacro jp 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jnp 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
%imacro jl 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jnl 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jg 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jng 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jge 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jnge 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jle 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
%imacro jnle 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
%imacro jecxz 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%imacro jcxz 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
%imacro jmp 1.nolist
|
||||
%%start:
|
||||
%? %1
|
||||
%%end:
|
||||
%assign %%length %%end - %%start
|
||||
%if %%length > 2 && %%length < 5
|
||||
%warning __FILE__ __LINE__ %? %1 %%length
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%endif
|
||||
[list +]
|
||||
984
test/ecm/lmacros/lmacros1.mac
Normal file
984
test/ecm/lmacros/lmacros1.mac
Normal file
@@ -0,0 +1,984 @@
|
||||
[list -]
|
||||
%if 0
|
||||
|
||||
NASM macro collection
|
||||
Public Domain by C. Masloch, 2008-2012
|
||||
Intended for 86 Mode programs.
|
||||
|
||||
%endif
|
||||
|
||||
%ifndef __lMACROS1_MAC__
|
||||
%assign __lMACROS1_MAC__ 1
|
||||
|
||||
%if !!2 - 1
|
||||
%error Unary operator ! returns values > 1. Adjust all sources.
|
||||
%endif
|
||||
|
||||
%idefine by byte
|
||||
%idefine wo word
|
||||
%idefine dwo dword
|
||||
|
||||
%idefine b byte
|
||||
%idefine w word
|
||||
%idefine d dword
|
||||
|
||||
%idefine s short
|
||||
%idefine sho short
|
||||
|
||||
%idefine n near
|
||||
%idefine ne near
|
||||
|
||||
%idefine f far
|
||||
|
||||
|
||||
; Bind major and minor version byte to version word or
|
||||
; version word with exchanged bytes.
|
||||
%idefine ver(major,minor) ( ((major)&0FFh)<<8|((minor)&0FFh) )
|
||||
%idefine verx(major,minor) ( ((minor)&0FFh)<<8|((major)&0FFh) )
|
||||
|
||||
; Macros for table creation
|
||||
%define count(start,stop) stop-start+1
|
||||
%define range(start,stop) (start),count(start,stop) ; generates two comma-separated values
|
||||
|
||||
; Work with 4-byte dates
|
||||
%define date4b(y,m,d) (((y)&0FFFFh)<<16|((m)&0FFh)<<8|((d)&0FFh)) ; create 4-byte date
|
||||
%define year4bd(d) (((d)>>16)&0FFFFh) ; get year from 4-byte date
|
||||
%define month4bd(d) (((d)>>8)&0FFh) ; get month from 4-byte date
|
||||
%define day4bd(d) ((d)&0FFh) ; get day from 4-byte date
|
||||
; The 4-byte date stores the year 0-65535 in the high word,
|
||||
; followed by the month 0-255 in the high byte (of the low
|
||||
; word) and the day 0-255 in the low byte.
|
||||
|
||||
|
||||
; Write numbers as decimal digits into a string
|
||||
%define _1digits_nocheck(d) (((d)% 10)+'0')
|
||||
%xdefine _2digits_nocheck(d) _1digits_nocheck((d)/10),_1digits_nocheck(d)
|
||||
%xdefine _3digits_nocheck(d) _1digits_nocheck((d)/100),_2digits_nocheck(d)
|
||||
%xdefine _4digits_nocheck(d) _1digits_nocheck((d)/1000),_3digits_nocheck(d)
|
||||
%xdefine _5digits_nocheck(d) _1digits_nocheck((d)/10000),_4digits_nocheck(d)
|
||||
%xdefine _1digits(d) (!!(d/10)*(1<<32)+ _1digits_nocheck(d))
|
||||
%xdefine _2digits(d) _1digits((d)/ 10),_1digits_nocheck(d)
|
||||
%xdefine _3digits(d) _1digits((d)/ 100),_2digits_nocheck(d)
|
||||
%xdefine _4digits(d) _1digits((d)/ 1000),_3digits_nocheck(d)
|
||||
%xdefine _5digits(d) _1digits((d)/10000),_4digits_nocheck(d)
|
||||
|
||||
; Write number as decimal digits into a string,
|
||||
; and automagically determine how many digits to use.
|
||||
; The input number is a critical expression to NASM.
|
||||
;
|
||||
; %1 = number to write
|
||||
; %2 = minimal number of digits, 0..5. defaults to 1
|
||||
; (setting it to 0 with a number of 0 writes nothing)
|
||||
%macro _autodigits 1-2.nolist 1
|
||||
%if %2 > 5
|
||||
%error Minimal number of digits 6 or more: %2
|
||||
%endif
|
||||
%if (%1) >= 100000
|
||||
%error Number has to use 6 or more digits: %1
|
||||
%elif (%1) >= 10000 || %2 == 5
|
||||
db _5digits(%1)
|
||||
%elif (%1) >= 1000 || %2 == 4
|
||||
db _4digits(%1)
|
||||
%elif (%1) >= 100 || %2 == 3
|
||||
db _3digits(%1)
|
||||
%elif (%1) >= 10 || %2 == 2
|
||||
db _2digits(%1)
|
||||
%elif (%1) >= 1 || %2 == 1
|
||||
db _1digits(%1)
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; %1 = name of single-line macro to set. will be prefixed by underscore
|
||||
; %2 = number to write
|
||||
; %3 = minimal number of digits, 0..5. defaults to 1
|
||||
; (setting it to 0 with a number of 0 defines macro to "")
|
||||
%macro _autodigitsdef 2-3.nolist 1
|
||||
%if %3 > 5
|
||||
%error Minimal number of digits 6 or more: %3
|
||||
%endif
|
||||
%if (%2) >= 100000
|
||||
%error Number has to use 6 or more digits: %2
|
||||
%elif (%2) >= 10000 || %3 == 5
|
||||
%define _%1 %[_5digits(%2)]
|
||||
%elif (%2) >= 1000 || %3 == 4
|
||||
%define _%1 %[_4digits(%2)]
|
||||
%elif (%2) >= 100 || %3 == 3
|
||||
%define _%1 %[_3digits(%2)]
|
||||
%elif (%2) >= 10 || %3 == 2
|
||||
%define _%1 %[_2digits(%2)]
|
||||
%elif (%2) >= 1 || %3 == 1
|
||||
%define _%1 %[_1digits(%2)]
|
||||
%elif
|
||||
%define _%1 ""
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Write numbers as hexadecimal digits into a string
|
||||
%define _1digitshex_nocheck(h) ( ((h)& 0Fh) + '0' + ('A'-'9'-1)*(((h)& 0Fh)/10) )
|
||||
%xdefine _2digitshex_nocheck(h) _1digitshex_nocheck((h)>> 4),_1digitshex_nocheck(h)
|
||||
%xdefine _3digitshex_nocheck(h) _1digitshex_nocheck((h)>> 8),_2digitshex_nocheck(h)
|
||||
%xdefine _4digitshex_nocheck(h) _1digitshex_nocheck((h)>>12),_3digitshex_nocheck(h)
|
||||
%xdefine _5digitshex_nocheck(h) _1digitshex_nocheck((h)>>16),_4digitshex_nocheck(h)
|
||||
%xdefine _6digitshex_nocheck(h) _1digitshex_nocheck((h)>>20),_5digitshex_nocheck(h)
|
||||
%xdefine _7digitshex_nocheck(h) _1digitshex_nocheck((h)>>24),_6digitshex_nocheck(h)
|
||||
%xdefine _8digitshex_nocheck(h) _1digitshex_nocheck((h)>>28),_7digitshex_nocheck(h)
|
||||
%xdefine _1digitshex(h) (!!(h&~0Fh)*(1<<32)+ _1digitshex_nocheck(h))
|
||||
%xdefine _2digitshex(h) _1digitshex((h)>> 4),_1digitshex_nocheck(h)
|
||||
%xdefine _3digitshex(h) _1digitshex((h)>> 8),_2digitshex_nocheck(h)
|
||||
%xdefine _4digitshex(h) _1digitshex((h)>>12),_3digitshex_nocheck(h)
|
||||
%xdefine _5digitshex(h) _1digitshex((h)>>16),_4digitshex_nocheck(h)
|
||||
%xdefine _6digitshex(h) _1digitshex((h)>>20),_5digitshex_nocheck(h)
|
||||
%xdefine _7digitshex(h) _1digitshex((h)>>24),_6digitshex_nocheck(h)
|
||||
%xdefine _8digitshex(h) _1digitshex((h)>>28),_7digitshex_nocheck(h)
|
||||
|
||||
|
||||
; Compute required words/dwords/qwords/paragraphs/pages/KiB of known byte size (rounds up if necessary)
|
||||
%idefine bytes(b) (b)
|
||||
%idefine words(b) ((b)+1>>1)
|
||||
%idefine dwords(b) ((b)+3>>2)
|
||||
%idefine qwords(b) ((b)+7>>3)
|
||||
%idefine paragraphs(b) ((b)+15>>4)
|
||||
%idefine paras(b) ((b)+15>>4)
|
||||
%idefine pages(b) ((b)+511>>9)
|
||||
%idefine kib(b) ((b)+1023>>10)
|
||||
|
||||
; Compute required bytes of known word/dword/qword/paragraph/page/KiB size
|
||||
%idefine frombytes(b) (b)
|
||||
%idefine fromwords(w) ((w)<<1)
|
||||
%idefine fromdwords(d) ((d)<<2)
|
||||
%idefine fromqwords(q) ((q)<<3)
|
||||
%idefine fromparagraphs(p) ((p)<<4)
|
||||
%idefine fromparas(p) ((p)<<4)
|
||||
%idefine frompages(p) ((p)<<9)
|
||||
%idefine fromkib(k) ((k)<<10)
|
||||
|
||||
|
||||
; Compute relative address
|
||||
;
|
||||
; address: which address is referenced
|
||||
; fixup: how many bytes are added to get the absolute address
|
||||
%define __REL__(address,fixup) ((address)-(fixup))
|
||||
%xdefine __REL8__(address,fixup) __REL__(address,fixup)
|
||||
%xdefine __REL8__(address) __REL__(address,$+1) ; for __JMP_REL8 (db)
|
||||
%xdefine __REL16__(address,fixup) __REL__(address,fixup)
|
||||
%xdefine __REL16__(address) __REL__(address,$+2); for __JMP_REL16 (dw)
|
||||
|
||||
; Values of some opcodes
|
||||
%define __JMP_REL8 0EBh
|
||||
%define __JMP_REL16 0E9h
|
||||
%define __JMP_FAR 0EAh
|
||||
%define __CALL_REL16 0E8h
|
||||
%define __CALL_FAR 9Ah
|
||||
%define __NOP 90h
|
||||
%define __TEST_IMM8 0A8h ; changes flags, NC
|
||||
%define __TEST_IMM16 0A9h ; changes flags, NC
|
||||
; Longer NOPs require two bytes, like a short jump does.
|
||||
; However they execute faster than unconditional jumps.
|
||||
; This one reads random data in the stack segment.
|
||||
; (Search for better ones.)
|
||||
%define __TEST_OFS16_IMM8 0F6h,86h ; changes flags, NC
|
||||
|
||||
; Remove the following macros if already found in other files
|
||||
%unimacro asciz 0-1+.nolist
|
||||
%unimacro ascii 0-1+.nolist
|
||||
%unmacro _ascii_prefix_suffix 2-3+.nolist
|
||||
%undef ascii
|
||||
%undef asciz
|
||||
%undef ascic
|
||||
%undef asciiline
|
||||
%undef ascizline
|
||||
%undef ascicline
|
||||
%unimacro call 1-*.nolist
|
||||
%unimacro verdef 4.nolist
|
||||
%unimacro numdef 1-3.nolist
|
||||
%unimacro strdef 3.nolist
|
||||
%unimacro incdef 2-4.nolist
|
||||
%unimacro _incdef 2-4.nolist
|
||||
%unimacro incdef 2-*.nolist
|
||||
%unimacro excdef 2-*.nolist
|
||||
%unimacro comment 0-*.nolist
|
||||
%unimacro commentif 2.nolist
|
||||
%unimacro commentifn 2.nolist
|
||||
%unimacro fixme 0-1+.nolist
|
||||
%unimacro noparam 0-1+.nolist
|
||||
%unimacro noparamnamed 1-2+.nolist
|
||||
%unimacro assignif 3-4.nolist
|
||||
%unimacro assignifn 3-4.nolist
|
||||
%unimacro cpu 1+.nolist ; removes NASM's standard macro
|
||||
%unimacro selcpu 0.nolist
|
||||
%unimacro cpufailmsg 0-2+.nolist
|
||||
%unimacro check186 0-1.nolist
|
||||
%unimacro check286 0-1.nolist
|
||||
%unimacro check386 0-1.nolist
|
||||
%unimacro check186 0-3.nolist
|
||||
%unimacro check286 0-3.nolist
|
||||
%unimacro check386 0-3.nolist
|
||||
%unimacro checkcpu 1.nolist
|
||||
%unimacro _d 2.nolist
|
||||
%unimacro d0out 0-3.nolist
|
||||
%unimacro endarea 1-2.nolist
|
||||
%unimacro struc 1.nolist ; removes NASM's standard macro
|
||||
%unimacro struc 1-2.nolist
|
||||
%unimacro endstruc 0.nolist ; removes NASM's standard macro
|
||||
%unimacro endstruc 0-1.nolist
|
||||
%unimacro istruc 1.nolist ; removes NASM's standard macro
|
||||
%unimacro at 1-2+.nolist ; removes NASM's standard macro
|
||||
%unimacro iend 0.nolist ; removes NASM's standard macro
|
||||
%unimacro fill 2-3+.nolist
|
||||
%unimacro _fill 3.nolist
|
||||
%unimacro pad 2-3+.nolist
|
||||
%unimacro _pad 3.nolist
|
||||
%unimacro alignd 2-3+.nolist
|
||||
|
||||
|
||||
|
||||
; String prefixed and/or suffixed with sequence(s)
|
||||
;
|
||||
; %1 = prefix
|
||||
; %2 = suffix
|
||||
; %3+ = Optional string
|
||||
%macro _ascii_prefix_suffix 2-3+.nolist
|
||||
db %1
|
||||
%ifnempty %3
|
||||
db %3
|
||||
%endif
|
||||
db %2
|
||||
%endmacro
|
||||
|
||||
%idefine ascii _ascii_prefix_suffix "","",
|
||||
%idefine asciz _ascii_prefix_suffix "",0,
|
||||
%idefine ascic _ascii_prefix_suffix "",36,
|
||||
%idefine asciiline _ascii_prefix_suffix "",{13,10},
|
||||
%idefine ascizline _ascii_prefix_suffix "",{13,10,0},
|
||||
%idefine ascicline _ascii_prefix_suffix "",{13,10,36},
|
||||
|
||||
; Counted string
|
||||
;
|
||||
; %1 = data type of count
|
||||
; %2+ = optional string
|
||||
%imacro _counted 2+.nolist
|
||||
%push
|
||||
%ifnempty %2
|
||||
_strlen %2
|
||||
%1 %$len
|
||||
db %2
|
||||
%else
|
||||
%1 0
|
||||
%endif
|
||||
%pop
|
||||
%endmacro
|
||||
%idefine counted _counted db,
|
||||
%idefine countedb _counted db,
|
||||
%idefine countedw _counted dw,
|
||||
|
||||
%imacro _strlen 1-*.nolist
|
||||
%assign %$len 0
|
||||
%rep %0
|
||||
%ifstr %1
|
||||
%strlen %$addlen %1
|
||||
%assign %$len %$len+%$addlen
|
||||
%elifnempty %1
|
||||
%assign %$len %$len+1
|
||||
%endif
|
||||
%rotate 1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
|
||||
; Call with word parameters behind opcode
|
||||
%imacro call 1-*.nolist
|
||||
%? %1
|
||||
%rep %0 - 1
|
||||
%rotate 1
|
||||
dw %1
|
||||
%endrep
|
||||
%endmacro
|
||||
|
||||
|
||||
; Define version information.
|
||||
;
|
||||
; %1 = Base name of single-line macros
|
||||
; %2 = Additional letter for base name of single-line macros
|
||||
; %3 = Major version
|
||||
; %4 = Minor version
|
||||
;
|
||||
; Created single-line macros:
|
||||
; %1_VER%2 = version word, high byte = major version
|
||||
; %1_VER%2_X = version word (bytes exchanged), high byte = minor version
|
||||
; %1_VER%2_MAJ = Major version number byte
|
||||
; %1_VER%2_MIN = Minor version number byte
|
||||
; %1_VER%2_STR = Up to 7 character version string (maximal "255.255")
|
||||
%imacro verdef 4.nolist
|
||||
%assign %1_VER%2_MAJ %3
|
||||
%assign %1_VER%2_MIN %4
|
||||
%assign %1_VER%2 ver(%3,%4)
|
||||
%assign %1_VER%2_X verx(%3,%4)
|
||||
%push
|
||||
%defstr %$maj %3
|
||||
%defstr %$min %4
|
||||
%if %4 < 10
|
||||
%strcat %$min '0', %$min ; one digit low numbers padded to two digits
|
||||
%endif
|
||||
%strcat %1_VER%2_STR %$maj, '.', %$min
|
||||
%pop
|
||||
%endmacro
|
||||
|
||||
; Define a numeric definition for conditional assembly
|
||||
;
|
||||
; Instead of:
|
||||
; %ifdef DEFINE
|
||||
; use:
|
||||
; %if _DEFINE
|
||||
;
|
||||
; %1 = Definition name. Will get an additional underscore prefix
|
||||
; %2 = Value to assign if not defined (defaults to 0)
|
||||
; %3 = Value to assign if defined, but empty (defaults to 1)
|
||||
%imacro numdef 1-3.nolist 0,1
|
||||
%ifnum __DEFAULTED_%1
|
||||
%if __lMACROS1_MAC__DEFAULTING && __DEFAULTED_%1
|
||||
%undef _%1 ; cause defaulting to take effect again
|
||||
%if __DEFAULTED_%1 == 2 ; defaulted to third parameter?
|
||||
%define _%1 ; cause alternative defaulting to take effect again
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
%ifdef _%1
|
||||
%ifempty _%1
|
||||
%assign _%1 %3 ; i.e. "-d_DEFINE" option on NASM's command line
|
||||
%if __lMACROS1_MAC__DEFAULTING
|
||||
%assign __DEFAULTED_%1 2 ; note alternative defaulting occurred
|
||||
%endif
|
||||
%endif ; (if option was "-d_DEFINE=0", it's left as zero)
|
||||
%if __lMACROS1_MAC__DEFAULTING
|
||||
%ifnnum __DEFAULTED_%1
|
||||
%assign __DEFAULTED_%1 0 ; note no defaulting occurred
|
||||
%endif
|
||||
%endif
|
||||
%else ; If not defined (no option on NASM's command line)
|
||||
%assign _%1 %2 ; then assign to zero
|
||||
%if __lMACROS1_MAC__DEFAULTING
|
||||
%assign __DEFAULTED_%1 1 ; note defaulting occurred
|
||||
%endif
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
; Define a generic definition for conditional assembly
|
||||
;
|
||||
; %1 = Definition name. Will get an additional underscore prefix
|
||||
; %2 = What to define as if not defined (defaults to empty)
|
||||
; %3 = What to define as if defined, but empty (defaults to empty)
|
||||
%imacro gendef 1-3.nolist
|
||||
%ifnum __DEFAULTED_%1
|
||||
%if __lMACROS1_MAC__DEFAULTING && __DEFAULTED_%1
|
||||
%undef _%1 ; cause defaulting to take effect again
|
||||
%if __DEFAULTED_%1 == 2 ; defaulted to third parameter?
|
||||
%define _%1 ; cause alternative defaulting to take effect again
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
%ifdef _%1
|
||||
%ifempty _%1
|
||||
%define _%1 %3 ; i.e. "-d_DEFINE" option on NASM's command line
|
||||
%if __lMACROS1_MAC__DEFAULTING
|
||||
%assign __DEFAULTED_%1 2 ; note alternative defaulting occurred
|
||||
%endif
|
||||
%endif ; (if option was "-d_DEFINE=0", it's left as zero)
|
||||
%if __lMACROS1_MAC__DEFAULTING
|
||||
%ifnnum __DEFAULTED_%1
|
||||
%assign __DEFAULTED_%1 0 ; note no defaulting occurred
|
||||
%endif
|
||||
%endif
|
||||
%else ; If not defined (no option on NASM's command line)
|
||||
%define _%1 %2 ; then define to default
|
||||
%if __lMACROS1_MAC__DEFAULTING
|
||||
%assign __DEFAULTED_%1 1 ; note defaulting occurred
|
||||
%endif
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
;; %macro __help_strdef_stringify 3+.nolist
|
||||
;;%xdefine _%1 %2%3%2
|
||||
;; %endmacro
|
||||
|
||||
; Define a string definition
|
||||
;
|
||||
; %1 = Definition name. Will get an additional underscore prefix
|
||||
; %2 = Value to assign if not defined
|
||||
; %3 = Value to assign if defined, but no string (if not given, %2)
|
||||
;
|
||||
; Using braces { and } is useful for %2 and %3
|
||||
%imacro strdef 2-3.nolist
|
||||
%ifnum __DEFAULTED_%1
|
||||
%if __lMACROS1_MAC__DEFAULTING && __DEFAULTED_%1
|
||||
%undef _%1 ; cause defaulting to take effect again
|
||||
%if __DEFAULTED_%1 == 2 ; defaulted to third parameter?
|
||||
%define _%1 ; cause alternative defaulting to take effect again
|
||||
%endif
|
||||
%endif
|
||||
%endif
|
||||
%ifdef _%1
|
||||
%ifempty _%1
|
||||
%if %0 >= 3
|
||||
%define _%1 %3 ; i.e. "-d_DEFINE" option on NASM's command line
|
||||
%if __lMACROS1_MAC__DEFAULTING
|
||||
%assign __DEFAULTED_%1 2 ; note alternative defaulting occurred
|
||||
%endif
|
||||
%else
|
||||
%define _%1 %2
|
||||
%if __lMACROS1_MAC__DEFAULTING
|
||||
%assign __DEFAULTED_%1 1 ; note defaulting occurred
|
||||
%endif
|
||||
%endif
|
||||
%else
|
||||
%ifnstr _%1
|
||||
; refer to http://stackoverflow.com/questions/15650276/nasm-convert-integer-to-string-using-preprocessor
|
||||
%defstr _%1 _%1
|
||||
; %define %%quot "
|
||||
; %define %%stringify(x) %%quot %+ x %+ %%quot
|
||||
; %xdefine _%1 %%stringify(_%1)
|
||||
;; __help_strdef_stringify %1, ", _%1
|
||||
; issue: leading and trailing blanks are deleted out of the string.
|
||||
; workaround: quote the content so that it's a string already.
|
||||
; ie this may need nasm source.asm -D_"' content '"
|
||||
%endif
|
||||
%endif ; (if option was "-d_DEFINE='FOO'", it's left as 'FOO')
|
||||
%else ; If not defined (no option on NASM's command line)
|
||||
%define _%1 %2 ;
|
||||
%if __lMACROS1_MAC__DEFAULTING
|
||||
%assign __DEFAULTED_%1 1 ; note defaulting occurred
|
||||
%endif
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Include definitions if a condition is met
|
||||
;
|
||||
; %1 = condition
|
||||
; %2-* = included definition name, without underscore prefix
|
||||
%imacro incdef 2-*.nolist
|
||||
%if %1 ; if true
|
||||
%rep (%0 - 1)
|
||||
%rotate 1
|
||||
%assign _%1 1 ; set any included to true
|
||||
%endrep
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Exclude definitions if a condition is met
|
||||
;
|
||||
; %1 = condition
|
||||
; %2-* = excluded definition name, without underscore prefix
|
||||
%imacro excdef 2-*.nolist
|
||||
%if %1 ; if true
|
||||
%rep (%0 - 1)
|
||||
%rotate 1
|
||||
%assign _%1 0 ; set any excluded to false
|
||||
%endrep
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%imacro overridedef 1-2.nolist 0
|
||||
%push OVERRIDE
|
||||
%ifdef _%1
|
||||
%assign %$defined 1
|
||||
%else
|
||||
%assign %$defined 0
|
||||
%endif
|
||||
%xdefine %$prior _%1
|
||||
%xdefine %$defaulted __DEFAULTED_%1
|
||||
%define %$name %1
|
||||
%assign _%1 %2
|
||||
%assign __DEFAULTED_%1 0
|
||||
%endmacro
|
||||
|
||||
%imacro resetdef 0-1.nolist
|
||||
%ifnctx OVERRIDE
|
||||
%error Wrong context
|
||||
%endif
|
||||
%if %0
|
||||
%ifnidn %1, %$name
|
||||
%error Wrong usage of resetdef
|
||||
%endif
|
||||
%endif
|
||||
%xdefine _%[%$name] %$prior
|
||||
%xdefine __DEFAULTED_%[%$name] %$defaulted
|
||||
%ifn %$defined
|
||||
%undef _%[%$name]
|
||||
%endif
|
||||
%pop
|
||||
%endmacro
|
||||
|
||||
|
||||
%assign __lMACROS1_MAC__DEFAULTING 0
|
||||
%imacro defaulting 0-1.nolist 1
|
||||
%ifidni %1,toggle
|
||||
%assign __lMACROS1_MAC__DEFAULTING !__lMACROS1_MAC__DEFAULTING
|
||||
%else
|
||||
%assign __lMACROS1_MAC__DEFAULTING !!(%1)
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
numdef _lMACROS1_MAC__CPU_DEFAULTS
|
||||
%if __lMACROS1_MAC__CPU_DEFAULTS
|
||||
numdef 186 ; 186 opcodes allowed
|
||||
numdef 386 ; 386 opcodes allowed
|
||||
incdef _386,186 ; excluding 186 opcodes on 386+ seems not useful
|
||||
%endif
|
||||
|
||||
numdef _lMACROS1_MAC__DEBUG_DEFAULTS
|
||||
%if __lMACROS1_MAC__DEBUG_DEFAULTS
|
||||
numdef DEBUG ; all of the debugging levels
|
||||
incdef _DEBUG,DEBUG0,DEBUG1,DEBUG2,DEBUG3,DEBUG4
|
||||
numdef DEBUG0 ; 1st level debug
|
||||
numdef DEBUG1 ; 2nd level debug
|
||||
numdef DEBUG2 ; 3rd level debug
|
||||
numdef DEBUG3 ; 4th level debug
|
||||
numdef DEBUG4 ; 5th level debug
|
||||
; Note: All specific debug levels are independent.
|
||||
; What each debug level does is program-specific.
|
||||
%endif
|
||||
|
||||
|
||||
; Automatically select CPU depending on definitions
|
||||
;
|
||||
; Use "hardwired" cpu directives instead in source files that
|
||||
; don't include code for multiple CPU generations.
|
||||
%imacro selcpu 0.nolist
|
||||
%if _386
|
||||
cpu 386
|
||||
%elif _186
|
||||
cpu 186
|
||||
%else
|
||||
cpu 8086
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Write a message stating what CPU type is required.
|
||||
;
|
||||
; %1 = Part of message before numerical CPU identifier (Defaults to "")
|
||||
; %2 = Part of message after numerical CPU identifier (Defaults to ASCIZ " CPU required")
|
||||
;
|
||||
; Using braces { and } is useful
|
||||
;
|
||||
; No data is generated if assembling for 8086
|
||||
%imacro cpufailmsg 0-2+.nolist "",{" CPU required",0}
|
||||
%if _386
|
||||
db %1, "386", %2
|
||||
%elif _186
|
||||
db %1, "186", %2
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Check if required CPU is available
|
||||
;
|
||||
; The code uses cx, ax and comparison flags.
|
||||
;
|
||||
; %1 = Code to execute if CPU requirement not meet
|
||||
%imacro checkcpu 1.nolist
|
||||
%if _386
|
||||
%%checkcpu: check386
|
||||
.fail:
|
||||
%1
|
||||
.pass:
|
||||
%elif _186
|
||||
%%checkcpu: check186
|
||||
.fail:
|
||||
%1
|
||||
.pass:
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Check for 186+ CPU
|
||||
;
|
||||
; %1 = true if .fail follows (jump to .pass),
|
||||
; false if .pass follows (jump to .fail)
|
||||
; Default true
|
||||
; %2 = label to jump to if 186+ CPU
|
||||
; Default .pass
|
||||
; %3 = label to jump to if no 186+ CPU
|
||||
; Default .fail
|
||||
%imacro check186 0-3 1 .pass .fail
|
||||
mov cx, 1_0010_0001b ; Shift count's bit 0 and 5 are set; shift data is 1
|
||||
shl ch, cl ; 186+ limits shift count to five bits (0-4): resulting
|
||||
; ch is 10b on 186+; 0 on 8086 (actual result overflows)
|
||||
%if %1
|
||||
jnz %2 ; 186+ -->
|
||||
%else
|
||||
jz %3 ; 8086 -->
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Check for 286+ CPU
|
||||
;
|
||||
; %1 = true if .fail follows (jump to .pass),
|
||||
; false if .pass follows (jump to .fail)
|
||||
; Default true
|
||||
; %2 = label to jump to if 286+ CPU
|
||||
; Default .pass
|
||||
; %3 = label to jump to if no 286+ CPU
|
||||
; Default .fail
|
||||
|
||||
%imacro check286 0-3 1 .pass .fail
|
||||
push sp
|
||||
pop ax
|
||||
cmp ax, sp ; 286+ pushes original sp value
|
||||
%if %1
|
||||
je %2 ; 286+ -->
|
||||
%else
|
||||
jne %3 ; 8086 or 186 -->
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Check for 386+ CPU
|
||||
;
|
||||
; %1 = true if .fail follows (jump to .pass),
|
||||
; false if .pass follows (jump to .fail)
|
||||
; Default true
|
||||
; %2 = label to jump to if 386+ CPU
|
||||
; Default .pass
|
||||
; %3 = label to jump to if no 386+ CPU
|
||||
; Default .fail
|
||||
%imacro check386 0-3 1 .pass .fail
|
||||
check286 0, {%2}, {%3} ; branches to .fail if 8086 or 186 -->
|
||||
[cpu 286]
|
||||
pushf
|
||||
push wo 0111_0000_0000_0000b
|
||||
popf ; set bits 12-14 of FLAGS ("push imm16" instruction 186+)
|
||||
pushf
|
||||
pop ax ; get what was in FLAGS
|
||||
popf ; restore original flags
|
||||
test ax, 0111_0000_0000_0000b ; 386+ leaves what we pushed; 286 clears bits 12-14 in
|
||||
; Real Mode (Bits 12-14 are used in Protected Mode only)
|
||||
__CPU__
|
||||
%if %1
|
||||
jnz %2 ; 386+ -->
|
||||
%else
|
||||
jz %3 ; 286 -->
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Instruction if specified level debug definition true
|
||||
;
|
||||
; %1 = Level of requested debug definition
|
||||
; %2 = Instruction
|
||||
%imacro _d 2+.nolist
|
||||
%if _DEBUG%1
|
||||
%2
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Instruction if xth level debug definition true
|
||||
;
|
||||
; %1+ = Instruction
|
||||
%idefine d0 _d 0,
|
||||
%idefine d1 _d 1,
|
||||
%idefine d2 _d 2,
|
||||
%idefine d3 _d 3,
|
||||
%idefine d4 _d 4,
|
||||
|
||||
; Breakpoint if xth level debug definition true
|
||||
%idefine dbp _d, __DEBUG_BP__
|
||||
%idefine d0bp d0 __DEBUG0_BP__
|
||||
%idefine d1bp d1 __DEBUG1_BP__
|
||||
%idefine d2bp d2 __DEBUG2_BP__
|
||||
%idefine d3bp d3 __DEBUG3_BP__
|
||||
%idefine d4bp d4 __DEBUG4_BP__
|
||||
%idefine dd0bp _d,{d0bp}
|
||||
%idefine dd1bp _d,{d1bp}
|
||||
%idefine dd2bp _d,{d2bp}
|
||||
%idefine dd3bp _d,{d3bp}
|
||||
%idefine dd4bp _d,{d4bp}
|
||||
|
||||
; Breakpoint instructions for all debug levels
|
||||
;
|
||||
; "call ...", "int1", "int3" are useful single-instruction breakpoints
|
||||
%define __DEBUG_BP__ int3
|
||||
%define __DEBUG0_BP__ int3
|
||||
%define __DEBUG1_BP__ int3
|
||||
%define __DEBUG2_BP__ int3
|
||||
%define __DEBUG3_BP__ int3
|
||||
%define __DEBUG4_BP__ int3
|
||||
|
||||
; Print number if 1st level debug definition true
|
||||
;
|
||||
; %1 = Number to display (in range 0-255)
|
||||
; %2 = Override call for "call __DEBUG0_DISPALDEC__"
|
||||
; %3 = Override call for "call __DEBUG0_DISPAL__"
|
||||
;
|
||||
; The calls have to preserve all registers except ax.
|
||||
%macro d0out 0-3.nolist -,call __DEBUG0_DISPALDEC__,call __DEBUG0_DISPAL__
|
||||
%if _DEBUG0
|
||||
push ax
|
||||
%ifnidn %1,-
|
||||
mov al, %1
|
||||
%2
|
||||
%endif
|
||||
mov al, '.'
|
||||
%3
|
||||
pop ax
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; cpu macro replacement
|
||||
;
|
||||
; __CPU__ = like __SECT__ (that is, use [cpu ...] and switch back with __CPU__)
|
||||
%imacro cpu 1+.nolist
|
||||
%define __CPU__ [cpu %1]
|
||||
__CPU__
|
||||
%endmacro
|
||||
|
||||
; Define size of area
|
||||
;
|
||||
; %1 = Starting label of area
|
||||
; %2 = if true, use already defined label %1_size (for
|
||||
; use with NASM's struc and endstruc); default is false
|
||||
;
|
||||
; Provided labels: %1_size (byte), %1_size_b (same),
|
||||
; %1_size_w (words), %1_size_d (dwords), %1_size_q
|
||||
; (qwords), %1_size_p (paragraphs), %1_size_pg (pages),
|
||||
; %1_size_ki (KiB).
|
||||
%imacro endarea 1-2.nolist 0
|
||||
%ifn %2
|
||||
%1_size equ $ - %1
|
||||
%endif
|
||||
%1_size_b equ %1_size
|
||||
%1_size_w equ %1_size+1 >>1
|
||||
%1_size_d equ %1_size+3 >>2
|
||||
%1_size_q equ %1_size+7 >>3
|
||||
%1_size_p equ %1_size+15 >>4
|
||||
%1_size_pg equ %1_size+511 >>9
|
||||
%1_size_ki equ %1_size+1023 >>10
|
||||
%endmacro
|
||||
|
||||
; The following macros replace NASM's standard struc macros.
|
||||
; They add support for non-zero starting offsets of structures
|
||||
; (optional %2 of struc is starting offset) and creating endarea's
|
||||
; various size definitions with endstruc (if optional %1 of endstruc
|
||||
; is true).
|
||||
%imacro struc 1-2.nolist 0
|
||||
%push
|
||||
%define %$strucname %1
|
||||
[absolute %2]
|
||||
%$strucname:
|
||||
%endmacro
|
||||
%imacro endstruc 0-1.nolist 0
|
||||
%if %1
|
||||
endarea %$strucname
|
||||
%else
|
||||
%{$strucname}_size equ ($-%$strucname)
|
||||
%endif
|
||||
%pop
|
||||
__SECT__
|
||||
%endmacro
|
||||
|
||||
%imacro istruc 1.nolist
|
||||
%push
|
||||
%define %$strucname %1
|
||||
%$strucstart:
|
||||
%endmacro
|
||||
%imacro at 1-2+.nolist
|
||||
times (%1-%$strucname)-($-%$strucstart) db 0
|
||||
%2
|
||||
%endmacro
|
||||
%imacro iend 0.nolist
|
||||
times %{$strucname}_size-($-%$strucstart) db 0
|
||||
%pop
|
||||
%endmacro
|
||||
|
||||
|
||||
%imacro checkeven 1.nolist
|
||||
%ifnnum %1
|
||||
%error Number expected
|
||||
%endif
|
||||
%if %1 & 1
|
||||
%error Even value expected
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
; Fill data to specified byte size (specify data)
|
||||
;
|
||||
; %1 = Byte size to fill
|
||||
; %2 = Fill byte (eg 0, 90h, 32)
|
||||
; %3 = Actual instruction to place before filling (optional)
|
||||
%imacro fill 2-3+.nolist
|
||||
%%data:
|
||||
%3 ; Actual data if given, else expands to nothing
|
||||
_fill %1,%2,%%data
|
||||
%endmacro
|
||||
|
||||
|
||||
; Fill data to specified byte size (specify start label of data)
|
||||
;
|
||||
; %1 = Byte size to fill
|
||||
; %2 = Fill byte (eg 0, 90h, 32)
|
||||
; %3 = Start label of data
|
||||
%imacro _fill 3.nolist
|
||||
%if %1 < 0 ; hu?
|
||||
%error _fill: size is negative
|
||||
%elif $-(%3) < 0 ; should generate a phase error anyway. however
|
||||
%error _fill: start label must not be behind filling
|
||||
%elif (%1)-$+(%3) < 0 ; times would also throw an error then ("TIMES value x is negative")
|
||||
%error _fill: data too large, exceeds size ; but showing a more specific message won't hurt
|
||||
%endif
|
||||
times (%1)-$+(%3) db %2 ; Fill with fill byte to given size
|
||||
%endmacro
|
||||
|
||||
|
||||
; Pad data to specified byte boundary (specify data)
|
||||
;
|
||||
; Does _not_ pad relative to the section start but relative to the start of the data. Use
|
||||
; NASM's align (or alignd below) to pad (cough, cough... align) if you don't want that.
|
||||
;
|
||||
; %1 = Byte boundary
|
||||
; %2 = Pad byte (eg 0, 90h, 32)
|
||||
; %3 = Actual instruction to place before padding (optional, else macro creates nothing)
|
||||
%imacro pad 2-3+.nolist
|
||||
%%data:
|
||||
%3 ; Actual data if given, else expands to nothing
|
||||
_pad %1,%2,%%data
|
||||
%endmacro
|
||||
|
||||
|
||||
; Pad data to specified byte boundary (specify start label of data)
|
||||
;
|
||||
; Does _not_ pad relative to the section start but relative to the start of the data. Use
|
||||
; NASM's align (or alignd below) to pad (cough, cough... align) if don't you want that.
|
||||
;
|
||||
; %1 = Byte boundary
|
||||
; %2 = Pad byte (eg 0, 90h, 32)
|
||||
; %3 = Start label of data (if it equals $, no padding is created)
|
||||
%imacro _pad 3.nolist
|
||||
%if %1 < 0 ; hu?
|
||||
%error _pad: boundary is negative
|
||||
%elifn %1
|
||||
%error _pad: boundary is zero
|
||||
%elif $-%3 < 0 ; should generate a phase error anyway. however
|
||||
%error _pad: start label must not be behind padding
|
||||
%endif
|
||||
|
||||
%push
|
||||
%assign %$size $-%3 ; size of data
|
||||
%assign %$count 0
|
||||
%rep %1 ; must be at the boundary then
|
||||
%ifn (%$count + %$size) % %1 ; if ( !((paddedcount + size) modulo boundary) )
|
||||
%exitrep ; then { we're done }
|
||||
%endif
|
||||
%assign %$count %$count+1 ; else keep counting
|
||||
%endrep
|
||||
%if %$count >= %1 ; if loop end caused by %endrep
|
||||
%error pad: an unknown error occured
|
||||
%endif
|
||||
times (%$count-1) db %2 ; put this data for the assembler. but in _one_ line
|
||||
%pop
|
||||
%endmacro
|
||||
|
||||
|
||||
; Similar to pad but using align:
|
||||
;
|
||||
; %1 = Byte boundary (relative from the section start)
|
||||
; %2 = Align byte (eg 0, 90h, 32)
|
||||
; %3 = Actual instruction to place before aligning (optional, else macro still aligns!)
|
||||
%imacro alignd 2-3+.nolist
|
||||
%3
|
||||
%if %1 < 0 ; hu?
|
||||
%error alignd: boundary is negative
|
||||
%elifn %1
|
||||
%error alignd: boundary is zero
|
||||
%else
|
||||
align %1,db %2
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
; Comment a line out
|
||||
;
|
||||
; Purpose: In front of instructions that are only to be created if
|
||||
; an expressions results in true, place a valid single-line
|
||||
; macro name. Then use the commentif (or commentifn) macro
|
||||
; below to create a single-line macro from an expression.
|
||||
;
|
||||
; This will use the macro "comment" so the instructions won't
|
||||
; assemble if the expression doesn't result in true. (Or
|
||||
; if the expression doesn't result in false, in case of
|
||||
; commentifn.) Else the single-line macro gets defined to
|
||||
; nothing causing the instructions to assemble. This "comment"
|
||||
; macro is required because you can't define a single-line
|
||||
; macro to the value of semicolon (";") with the preprocessor
|
||||
; for obvious reasons. (It will think a real comment starts
|
||||
; with the semicolon ;)
|
||||
%imacro comment 0-*.nolist
|
||||
%endmacro
|
||||
|
||||
|
||||
; Specify a single-line macro for above comment macro purpose
|
||||
;
|
||||
; %1 = expression (gets placed after %if)
|
||||
; %2 = single-line macro (gets underscore prefix)
|
||||
%imacro commentif 2.nolist
|
||||
%if %1
|
||||
%define _%2 comment ; define it to invoke comment
|
||||
%else
|
||||
%define _%2 ; define it to a zero string
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
; Like commentif, but expression gets placed after %ifn
|
||||
%imacro commentifn 2.nolist
|
||||
%ifn %1
|
||||
%define _%2 comment ; define it to invoke comment
|
||||
%else
|
||||
%define _%2 ; define it to a zero string
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
; Aborts assembling if found anywhere within source
|
||||
%imacro fixme 0-1+.nolist
|
||||
%error %1
|
||||
%endmacro
|
||||
|
||||
|
||||
; Comment a line out but make sure there are no parameters
|
||||
%imacro noparam 0-1+.nolist
|
||||
%if %0
|
||||
%error Must not have parameters.
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
; Like noparam, except %1 is a message to display
|
||||
%imacro noparamnamed 1-2+.nolist
|
||||
%ifnempty %2
|
||||
%error %1: Must not have parameters.
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
; Assign a single-line macro to an value if a condition matches, else zero
|
||||
;
|
||||
; %1 = expression (gets placed after %if)
|
||||
; %2 = single-line macro (gets underscore prefix)
|
||||
; %3 = value if condition matches
|
||||
; %4 = value if condition doesn't match (default: 0)
|
||||
%imacro assignif 3-4.nolist 0
|
||||
%if %1
|
||||
%assign _%2 %3
|
||||
%else
|
||||
%assign _%2 %4
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
; Like assignif, but expression gets placed after %ifn
|
||||
%imacro assignifn 3-4.nolist 0
|
||||
%ifn %1
|
||||
%assign _%2 %3
|
||||
%else
|
||||
%assign _%2 %4
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
%endif
|
||||
[list +]
|
||||
1207
test/ecm/lmacros/lmacros2.mac
Normal file
1207
test/ecm/lmacros/lmacros2.mac
Normal file
File diff suppressed because it is too large
Load Diff
121
test/ecm/lmacros/lmacros3.mac
Normal file
121
test/ecm/lmacros/lmacros3.mac
Normal file
@@ -0,0 +1,121 @@
|
||||
[list -]
|
||||
%if 0
|
||||
|
||||
Extensions to NASM macro collection
|
||||
Public Domain by C. Masloch, 2019
|
||||
Intended for 86 Mode programs.
|
||||
|
||||
%endif
|
||||
|
||||
%ifndef __lMACROS3_MAC__
|
||||
%assign __lMACROS3_MAC__ 1
|
||||
|
||||
%include "lmacros2.mac"
|
||||
[list -]
|
||||
|
||||
|
||||
; This macro is used to generate byte or word access to specific
|
||||
; bits of a dword variable.
|
||||
; %1 = token: if "~", bit value will be negated after checking
|
||||
; %2 = instruction
|
||||
; %3 = variable, in the form "[address]" without size specification
|
||||
; %4 = bit value(s) to access
|
||||
; %5 = bool: disable word access warning, defaults to 0
|
||||
; If the value in %4 has bits set in different bytes so that
|
||||
; a single 8- or 16-bit instruction cannot access all the bits,
|
||||
; an error is displayed. This insures that the macro only has
|
||||
; to generate one instruction, as a 32-bit access on 16-bit
|
||||
; CPUs requires multiple instructions. This workaround code
|
||||
; needs to be written specifically then, or the flags have to
|
||||
; be re-ordered to allow the access.
|
||||
%macro _opt 4-5.nolist 0
|
||||
%push
|
||||
%defstr %$adr %3
|
||||
%strlen %$len %$adr
|
||||
%substr %$tf %$adr 1
|
||||
%substr %$tb %$adr %$len
|
||||
%substr %$adr %$adr 2,-2
|
||||
%deftok %$adr %$adr
|
||||
%%num: equ %4
|
||||
%assign %$num %%num
|
||||
%ifnidn %$tf,"["
|
||||
%error Invalid memory access syntax
|
||||
%elifnidn %$tb,"]"
|
||||
%error Invalid memory access syntax
|
||||
%elifn %$num
|
||||
%error Bit value is zero! Check code.
|
||||
%elifn (%$num) & ~0FFh
|
||||
%2 byte [%$adr], %1(%$num)
|
||||
%elifn (%$num) & ~0FF00h
|
||||
%2 byte [%$adr+1], %1((%$num)>>8)
|
||||
%elifn (%$num) & ~0FF0000h
|
||||
%2 byte [%$adr+2], %1((%$num)>>16)
|
||||
%elifn (%$num) & ~0FF000000h
|
||||
%2 byte [%$adr+3], %1((%$num)>>24)
|
||||
%elifn (%$num) & ~0FFFFh
|
||||
%ifn %5
|
||||
%warning Macro generated word access
|
||||
%endif
|
||||
%2 word [%$adr], %1(%$num)
|
||||
%elifn (%$num) & ~0FFFF00h
|
||||
%ifn %5
|
||||
%warning Macro generated word access
|
||||
%endif
|
||||
%2 word [%$adr+1], %1((%$num)>>8)
|
||||
%elifn (%$num) & ~0FFFF0000h
|
||||
%ifn %5
|
||||
%warning Macro generated word access
|
||||
%endif
|
||||
%2 word [%$adr+2], %1((%$num)>>16)
|
||||
%else
|
||||
%error Unsupported macro usage, requires dword:
|
||||
%ifempty %1
|
||||
%error %2 dword [%$adr], %$num
|
||||
%else
|
||||
%error %2 dword [%$adr], %1(%$num)
|
||||
%endif
|
||||
%endif
|
||||
%pop
|
||||
%endmacro
|
||||
|
||||
; User forms for above macro.
|
||||
; %1 = variable, in the form "[address]" without size specification
|
||||
; %2 = bit value(s) to access
|
||||
; %3 = bool: disable word access warning, defaults to 0
|
||||
; testopt tests the specified bits (using a "test" instruction) and
|
||||
; leaves a meaningful result in ZF, as well as NC.
|
||||
; clropt clears the specified bits (using an "and" instruction with
|
||||
; the negated value) and leaves NC, but a random ZF.
|
||||
; setopt sets the specified bits (using an "or" instruction) and
|
||||
; leaves NC, NZ.
|
||||
; xoropt toggles the specified bits (using a "xor" instruction) and
|
||||
; leaves NC, but a random ZF.
|
||||
%idefine testopt _opt ,test,
|
||||
%idefine clropt _opt ~,and,
|
||||
%idefine setopt _opt ,or,
|
||||
%idefine xoropt _opt ,xor,
|
||||
|
||||
|
||||
%imacro addsection 1-2.nolist
|
||||
%ifdef _SECTION_ADDED_%1
|
||||
%error Section %1 already added
|
||||
%endif
|
||||
section %1 %2
|
||||
%define _SECTION_ADDED_%1 1
|
||||
usesection %1
|
||||
%endmacro
|
||||
|
||||
%imacro usesection 1-2.nolist 0
|
||||
%ifndef _SECTION_ADDED_%1
|
||||
%error Section %1 not yet added
|
||||
%endif
|
||||
%if %2
|
||||
[section %1]
|
||||
%else
|
||||
section %1
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
%endif
|
||||
[list +]
|
||||
Reference in New Issue
Block a user