flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > macro to print mixed strings, registers, uint32, floats |
Author |
|
wht36 22 Dec 2008, 14:40
While I prefer FASM, the people at MASM32 has a lot of nice code snippets, many of which uses the MASM32 print macro to output the results, which has been the most difficult part for me when I try to port their code to FASM.
So after much hair tearing, I made a FASM version of a simplified print macro to output mixed strings, constants, registers, unsigned 32 bit integers, and floats at runtime. All are welcome to improve it. It certainly needs a lot of improvement still (the integer and float to decimal conversion routines are particularly primitive...). So here's the arguments that print accepts. Code: print "A string\n" ; use \n to embed a newline print an_equate ; integers will be zero suppressed, floats will be displayed as is print real8 addr_myfloat ; only accepts qword floats currently (sorry~~) print eax ; outputs value of EAX in decimal format print [uint32_in_memory] print 8 eax ; output EAX in decimal with right justification to e.g. 8 columns The arguments can be combined, and if the exact same arguments has been used before, print will recognise it and reuse the data (which may not always be the best thing to do). Note that print outputs assembly constants as a decimal string but as a side effect, "print 13,10" will output "1310" and not cr/lf (so use "\n" to output cr/lf)! Okay, so here are the macros (pushreal8 & pushdec are procedures to convert number to strings and are not shown, but are included in the full source download) Code: idata equ macro .data [args] { common local z macro idata \{ idata z \} macro z args } idata? equ macro .data? [args] { common local z macro idata? \{ idata? z \} macro z args } ;Macro to store mixed code and data macro dbdata [data] { common local alabel, dbmac data_list equ data_list dbmac ^ ; save run time macro for re-use .data \{ alabel: \} macro dbmac \{ ;create macro to store run time code data_addr equ alabel data_size equ alabel\#.size \} forward local ..blabel .data \{ if data eqtype "" ; store string as is, replacing \n with cr,lf @@: db data repeat $-@b-1 load char word from @b+%-1 if char = "\n" store word 0A0Dh at @b+%-1 end if end repeat else if data eqtype 9 eax | data eqtype 9 [] match num var,data \\{ times num db " " \\} else if data eqtype eax | data eqtype [] db " " ; right justify register/memory contents else if data eqtype real8 var db " " else if data eqtype 0 ; strip leading zeroes local dividend, divisor divisor = 1 dividend = data while dividend >= 10* divisor divisor = divisor * 10 end while while divisor > 1 db (dividend/divisor)+"0" dividend = dividend mod divisor divisor = divisor/10 end while db dividend+"0" else if data eqtype 0.0 match num,data \\{ ; store float as quoted string db \\`num \\} end if ..blabel: \} macro dbmac \{ ; runtime code to store dbmac if data eqtype eax | data eqtype [] stdcall pushdec,dword data,..blabel else if data eqtype 9 eax | data eqtype 9 [] match num var,data \\{ stdcall pushdec,dword var,..blabel \\} end if match =real8 var,data \\{ mov esi,..blabel mov edi,var call pushreal8 \\} \} common .data \{ .size = $-alabel \} dbmac ; store run time code } ;This macro stores mixed code & data, it supports storing ; quoted string (use "\n" to store a new line) ; constants (e.g. 13.0 stored as '13.0') ; registers/[memory] (runtime conversion to decimal with 10 digits right justification), ; n register/[memory] (as above with n digits justification) ; and REAL8 memory floats (real8 mem_addr, right justified with 14 digits) ;It returns data_addr (address of the data stored) and data_size (size of the data stored) ;Note: if previous identical arguments have been used, it will reuse it macro adddata [arg] { common data_addr equ match full,arg \{ ; expand argument concat equ irp val,full \\{ ; remove comma's match any,concat \\\{ concat equ any val irps val2,val \\\\{ ; remove spaces key equ any=\\\\#val2 ; add = for exact search \\\\} \\\} match ,concat \\\{ irps val2,val \\\\{ match bl,concat \\\\\{ concat equ bl val2 key equ bl=\\\\\#val2 \\\\\} match ,concat \\\\\{ concat equ val2 key equ val2 \\\\\} \\\\} \\\} \\} match all,key \\{ ; expand search key match any [=all] dmac ^,data_list\\\{ ; if argument used before dmac ; use old data \\\} match ,data_addr \\\{ ; else data_list equ data_list [concat] ; record new data dbdata full ; process one by one \\\} \\} \} } ;Prints mixed data to stdout ;e.g. print "EAX is ",eax macro print [arg] { common adddata arg match =print_init,print_init \{ .data? \\{ hStdout rd 1 byteswritten rd 1 \\} invoke GetStdHandle,STD_OUTPUT_HANDLE mov [hStdout],eax print_init equ 1 \} stdcall stdout,data_addr,data_size } section '.text' code readable executable pushreal8: ... pushdec: ... section '.data' data readable writeable import ... idata idata? Attached clock_counters3.rar is an example source file using print. It is basically some profiler routines ported from MichaelW (masm32 lib), Abel ( http://www.masm32.com/board/index.php?topic=6774.0 ), Bastien ( http://board.flatassembler.net/topic.php?t=8684 ), and Petroizki ( http://www.masm32.com/board/index.php?topic=3724.0 )
Last edited by wht36 on 23 Dec 2008, 07:29; edited 1 time in total |
|||||||||||
22 Dec 2008, 14:40 |
|
rCX 22 Dec 2008, 19:04
Really cool. If I had more experience I would port it to DOS.
|
|||
22 Dec 2008, 19:04 |
|
wht36 23 Dec 2008, 12:12
Haven't programmed in DOS for a long time, but here it is, the "DOS" version. It works under windows XP console. I am not actually sure if will under real DOS though.
|
|||||||||||
23 Dec 2008, 12:12 |
|
vid 23 Oct 2010, 10:16
I still prefer printf-like strings. Looks nicer in code, and gives you much more formatting options.
|
|||
23 Oct 2010, 10:16 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.