The following macro I wrote may be useful for debuging macroinstructions. Thank Tomasz for the tips.
macro display_num value*, base
{
; fasm can only calculate values not bigger than
; 0xffffffffffffffff (64 bits), otherwise, out of
; range
local ..flag_found_bit
local ..highest_bit_pos
local ..counter
local ..tmp
local ..num
local ..backup_value
local ..backup_base
; backup args to avoid preprocessing side-effects
..backup_value = value
if base eqtype
..backup_base = 16
else
..backup_base = base
end if
..flag_found_bit = 0
..highest_bit_pos = 0
if ..backup_value = 0
..counter = 0 ; skip the repeat block
display '0'
else
..counter = 64
end if
; how many bits does the value have?
repeat ..counter
..tmp = (..backup_value shr %)
if ..tmp = 0 & ..flag_found_bit = 0
..highest_bit_pos = %
..flag_found_bit = 1
end if
end repeat
local ..base_mask
local ..base_mask_len
local ..base_tail
local ..flag_base10
..flag_base10=0
if ..backup_base = 2
..base_mask = 1
..base_mask_len = 1
..base_tail = 'B'
else if ..backup_base = 8
..base_mask = 7
..base_mask_len = 3
..base_tail = 'o'
else if ..backup_base = 10
..flag_base10 = 1
else if ..backup_base = 16
..base_mask = 15 ; 0xf
..base_mask_len = 4 ; 4 bits
..base_tail = 'H'
end if
; extract values
if ..flag_base10 = 1 ; Fixme: I don't know if there're some
if ..backup_value = 0 ; better ways to calc 10 based numbers
..counter = 0
else
if ..backup_value < 0
..tmp = 0 - ..backup_value
display '-'
else
..tmp = ..backup_value
end if
..counter = 19 ; maximal power fasm can afford
end if
local ..status
..status = 0
repeat ..counter
local ..exp
..exp = ..counter - %
; power calculation: 10^exp (exp >= 0)
local ..x
..x=1
repeat ..exp
..x = ..x * 10
end repeat
if ..tmp >= ..x
..status = 1 ; caught first leftmost
; non-zero digital
end if
if ..status = 1
..num = ..tmp / ..x
..tmp = ..tmp mod ..x
display '0' + ..num
end if
end repeat
..flag_base10 = 0
else
if (defined ..base_mask_len) & (defined ..base_mask)
..counter = ..highest_bit_pos / ..base_mask_len
if (..highest_bit_pos mod ..base_mask_len) > 0
..counter = ..counter + 1
end if
repeat ..counter
..tmp = ..backup_value shr ((..counter - %) * \
..base_mask_len)
if ..tmp <> 0
..num = ..tmp and ..base_mask
local ..char
if ..num > 9
..char = 'A' + ..num - 9 - 1
else
..char = '0' + ..num
end if
display ..char
end if
end repeat
display ..base_tail
else
display "Invalid base number."
end if
end if
}
Usage:
display_num <value> [,optional_base]
For example:
num = 0x123456789abcdef0
display_num num, 16 ; produce 123456789ABCDEF0H
display 13, 10
display_num num, 10 ;produce 1311768467463790320
display 13, 10
display_num num, 8 ;produce 110642547423257157360o
display 13, 10
display_num num, 2 ;produce 1001000110100010101100111100010011010101111001101111011110000B
display 13, 10
display_num num ;produce 123456789ABCDEF0H
display 13, 10
display_num num, 6 ; Invalid base number.