flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > Listing tool feature request

Author
Thread Post new topic Reply to topic
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 29 Jun 2009, 15:06
Tomasz, do you have any plans to provide an option to output a listing more like http://board.flatassembler.net/topic.php?t=5764 ? (Showing CPU-level instructions instead of macro invocations, etc)

Code:
0000000000401000: 55                                     push        rbp
0000000000401001: 48 89 E5                               mov         rbp, rsp
0000000000401004: 48 81 EC 00 04 00 00                   sub         rsp, localbytes?cf + alignment?cj
000000000040100B: 48 8D 95 00 FC FF FF                   lea         rdx, [ TempStr ]
0000000000401012: 48 83 EC 10                            sub         rsp, stackspace?d7
0000000000401016: 48 89 D1                               mov         rcx, rdx
0000000000401019: 48 8B 55 10                            mov         rdx, [ _String ]
000000000040101D: FF 15 06 00 00 00                      call        [ lstrcpy ]
0000000000401023: 48 83 C4 10                            add         rsp, stackspace?d7
0000000000401027: C9                                     leave      
0000000000401028: C3                                     retn       
0000000000401029: 00 00 00 00 00 00 00 00                lstrcpy dq 0
    

Instead of:
Code:
; LOTS OF LINES ABOVE
                                                                entry Function
                                                                
                                                                
00000200: 55 48 89 E5 48 81 EC 00 04 00 00                      proc Function, _String
                                                                        local   TempStr[1024]:BYTE
                                                                
0000020B: 48 8D 95 00 FC FF FF                                          lea     rdx, [TempStr]
00000212: 48 83 EC 10 48 89 D1 48 8B 55 10 FF 15 06 00 00               invoke  lstrcpy, rdx, [_String]
          00 48 83 C4 10                                        
00000227: C9 C3                                                         ret
                                                                endp
                                                                
00000229: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00       lstrcpy dq 0
    


Or:
Code:
format PE64 GUI

entry Function


;proc Function,_String



;match name params,Function,_String>
;{define@proc name,<params}
;define@proc Function,<,_String>
; params?Qz flag?R0 regs?R1 parmbytes?R2 localbytes?R3 current?R4
if used Function
Function:
;match=stdcall args,,_String{params?Qz equ args
; flag?R0=11b}
;match=stdcall,,_String{params?Qz equ
; flag?R0=11b}
;match=c args,,_String{params?Qz equ args
; flag?R0=10001b}
;match=c,,_String{params?Qz equ
; flag?R0=10001b}
;match=params?Qz,params?Qz{params?Qz equ,_String
; flag?R0=10000b}
;params?Qz equ,_String
flag?R0=10000b
virtual at rbp+16
;match=uses reglist=,args,,_String{regs?R1 equ reglist
; params?Qz equ args}
;match=regs?R1=uses reglist,regs?R1,_String{regs?R1 equ reglist
; params?Qz equ}
;match=regs?R1,regs?R1{regs?R1 equ}
;regs?R1 equ
;match=,args,,_String{defargs@proc args}
;defargs@proc _String


if~_String eq


; ..arg?R5 current@arg?R6
;match argname:type,_String
;{current@arg?R6 equ argname
; label ..arg?R5 type
; argname equ ..arg?R5
; if dqword eq type
; dq ?,?
; else if tbyte eq type
; dq ?,?
; else
; dq ?
; end if}
;match=current@arg?R6,current@arg?R6
;{current@arg?R6 equ _String
; _String equ ..arg?R5
; ..arg?R5 dq ?}
;current@arg?R6 equ _String
;_String equ ..arg?R5
..arg?R5 dq ?


;args@proc equ _String


;restore current@arg?R6


end if
;match=args@proc args,_String,_String{defargs@proc args}
parmbytes?R2=$-(rbp+16)
end virtual
Function%=parmbytes?R2/8
;all@vars equ
current?R4=0
;match prologue:reglist,prologuedef:<>{prologue Function,flag?R0,parmbytes?R2,localbytes?R3,reglist}
;prologuedef Function,flag?R0,parmbytes?R2,localbytes?R3,<>
; alignment?R7 counter?R8
if parmbytes?R2|localbytes?R3
push rbp
mov rbp,rsp
if localbytes?R3+alignment?R7
sub rsp,localbytes?R3+alignment?R7
end if
end if
counter?R8=0
;irps reg,{push reg
; counter?R8=counter?R8+1}
alignment?R7=8*(counter?R8 and 1)
;macro locals
;{virtual at rbp-localbytes?R3+current?R4
; macro label def \{ match . type,def>\\{ deflocal@proc .,label,<type \\} \}
; struc db[val]\{ common deflocal@proc .,db,val \}
; struc du[val]\{ common deflocal@proc .,du,val \}
; struc dw[val]\{ common deflocal@proc .,dw,val \}
; struc dp[val]\{ common deflocal@proc .,dp,val \}
; struc dd[val]\{ common deflocal@proc .,dd,val \}
; struc dt[val]\{ common deflocal@proc .,dt,val \}
; struc dq[val]\{ common deflocal@proc .,dq,val \}
; struc rb cnt \{ deflocal@proc .,rb cnt,\}
; struc rw cnt \{ deflocal@proc .,rw cnt,\}
; struc rp cnt \{ deflocal@proc .,rp cnt,\}
; struc rd cnt \{ deflocal@proc .,rd cnt,\}
; struc rt cnt \{ deflocal@proc .,rt cnt,\}
; struc rq cnt \{ deflocal@proc .,rq cnt,\}}
;macro endl
;{purge label
; restruc db,du,dw,dp,dd,dt,dq
; restruc rb,rw,rp,rd,rt,rq
; current?R4=$-(rbp-localbytes?R3)
; end virtual}
;macro ret operand
;{match any,operand \{ retn operand \}
; match,operand \{ match epilogue:reglist,epilogue@proc:<regs?R1>
; \\{ epilogue Function,flag?R0,parmbytes?R2,localbytes?R3,reglist \\} \}}
;macro finish@proc{localbytes?R3=(current?R4+15)and(not 15)
; end if}
;local TempStr[1024]:BYTE


;locals
virtual at rbp-localbytes?R3+current?R4
;macro label def{match . type,def>\{ deflocal@proc .,label,<type \}}
;struc db[val]{common deflocal@proc .,db,val}
;struc du[val]{common deflocal@proc .,du,val}
;struc dw[val]{common deflocal@proc .,dw,val}
;struc dp[val]{common deflocal@proc .,dp,val}
;struc dd[val]{common deflocal@proc .,dd,val}
;struc dt[val]{common deflocal@proc .,dt,val}
;struc dq[val]{common deflocal@proc .,dq,val}
;struc rb cnt{deflocal@proc .,rb cnt,}
;struc rw cnt{deflocal@proc .,rw cnt,}
;struc rp cnt{deflocal@proc .,rp cnt,}
;struc rd cnt{deflocal@proc .,rd cnt,}
;struc rt cnt{deflocal@proc .,rt cnt,}
;struc rq cnt{deflocal@proc .,rq cnt,}

;done@local equ
;match varname[count]:vartype,TempStr[1024]:BYTE
;{match=BYTE,vartype \{ varname rb count
; restore done@local \}
; match=WORD,vartype \{ varname rw count
; restore done@local \}
; match=DWORD,vartype \{ varname rd count
; restore done@local \}
; match=PWORD,vartype \{ varname rp count
; restore done@local \}
; match=QWORD,vartype \{ varname rq count
; restore done@local \}
; match=TBYTE,vartype \{ varname rt count
; restore done@local \}
; match=DQWORD,vartype \{ label varname dqword
; rq count+count
; restore done@local \}
; match,done@local \{ virtual
; varname vartype
; end virtual
; rb count*sizeof.#vartype
; restore done@local \}}
;match=BYTE,BYTE{TempStr rb 1024
; restore done@local}
;TempStr:;rb 1024
;deflocal@proc TempStr,rb 1024,


;match vars,{all@vars equ all@vars,}
;all@vars equ TempStr


; ..var?R9 ..tmp?RA
;match=label,rb 1024{..tmp?RA equ}
;match tmp,..tmp?RA{..var?R9 rb 1024}
..var?R9 rb 1024
;match,..tmp?RA{label ..var?R9}
;match=?,{..tmp?RA equ}
;match any=?,{..tmp?RA equ}
;match any(=?),{..tmp?RA equ}
;match tmp:value,..tmp?RA:
;{tmp:end virtual
; initlocal@proc ..var?R9,rb 1024 value
; virtual at tmp}


;match first rest,..var?R9,{TempStr equ first}
;TempStr equ ..var?R9
;restore done@local
;match=WORD,BYTE{TempStr rw 1024
; restore done@local}
;match=DWORD,BYTE{TempStr rd 1024
; restore done@local}
;match=PWORD,BYTE{TempStr rp 1024
; restore done@local}
;match=QWORD,BYTE{TempStr rq 1024
; restore done@local}
;match=TBYTE,BYTE{TempStr rt 1024
; restore done@local}
;match=DQWORD,BYTE{label TempStr dqword
; rq 1024+1024
; restore done@local}
;match,done@local{virtual
; TempStr BYTE
; end virtual
; rb 1024*sizeof.BYTE
; restore done@local}
;match:varname:vartype,done@local:..var?R9[1024]:BYTE
;{match=BYTE,vartype \{ varname db ?
; restore done@local \}
; match=WORD,vartype \{ varname dw ?
; restore done@local \}
; match=DWORD,vartype \{ varname dd ?
; restore done@local \}
; match=PWORD,vartype \{ varname dp ?
; restore done@local \}
; match=QWORD,vartype \{ varname dq ?
; restore done@local \}
; match=TBYTE,vartype \{ varname dt ?
; restore done@local \}
; match=DQWORD,vartype \{ label varname dqword
; dq ?,?
; restore done@local \}
; match,done@local \{ varname vartype
; restore done@local \}}
;match,done@local
;{TempStr[1024]:BYTE
; restore done@local}


;endl
;purge label
;restruc db,du,dw,dp,dd,dt,dq
;restruc rb,rw,rp,rd,rt,rq
current?R4=$-(rbp-localbytes?R3)
end virtual

lea rdx,[..var?R9]
;invoke lstrcpy,rdx,[_String]


;fastcall[lstrcpy],rdx,[_String]


; stackspace?RB argscount?RC counter?RD
if argscount?RC and 1
stackspace?RB=(argscount?RC+1)*8
else
stackspace?RB=argscount?RC*8
end if
counter?RD=0
if stackspace?RB
sub rsp,stackspace?RB
end if


if~rdx eq
counter?RD=counter?RD+1
if counter?RD<=4
if rdx eqtype 0
size@arg=8
else if rdx eqtype byte 0
virtual at 0
mov[rbx],rdx
; opcode?RE
load opcode?RE byte from 0
if opcode?RE and 0F8h=48h
size@arg=8
else if opcode?RE=66h
size@arg=2
else if opcode?RE=0C7h
size@arg=4
else
size@arg=1
end if
end virtual
else
virtual at 0
inc rdx
; opcode?RF
load opcode?RF byte from 0
if opcode?RF=67h
load opcode?RF byte from 1
end if
if opcode?RF and 0F8h=48h
size@arg=8
else if opcode?RF=66h
size@arg=2
else if opcode?RF=0FFh
size@arg=4
else
size@arg=1
end if
end virtual
end if
if counter?RD=1
if size@arg=8
if~rdx eq rcx
mov rcx,rdx
end if
else if size@arg=4
if~rdx eq ecx
mov ecx,rdx
end if
else if size@arg=2
if~rdx eq cx
mov cx,rdx
end if
else if size@arg=1
if~rdx eq cl
mov cl,rdx
end if
end if
else if counter?RD=2
if size@arg=8
if~rdx eq rdx
mov rdx,rdx
end if
else if size@arg=4
if~rdx eq edx
mov edx,rdx
end if
else if size@arg=2
if~rdx eq dx
mov dx,rdx
end if
else if size@arg=1
if~rdx eq dl
mov dl,rdx
end if
end if
else if counter?RD=3
if size@arg=8
if~rdx eq r8
mov r8,rdx
end if
else if size@arg=4
if~rdx eq r8d
mov r8d,rdx
end if
else if size@arg=2
if~rdx eq r8w
mov r8w,rdx
end if
else if size@arg=1
if~rdx eq r8b
mov r8b,rdx
end if
end if
else if counter?RD=4
if size@arg=8
if~rdx eq r9
mov r9,rdx
end if
else if size@arg=4
if~rdx eq r9d
mov r9d,rdx
end if
else if size@arg=2
if~rdx eq r9w
mov r9w,rdx
end if
else if size@arg=1
if~rdx eq r9b
mov r9b,rdx
end if
end if
end if
else
if rdx eqtype[0]|rdx eqtype byte[0]
virtual at 0
inc rdx
; opcode?RG
load opcode?RG byte from 0
end virtual
if opcode?RG and 0F8h=48h
mov rax,rdx
mov[rsp+(counter?RD-1)*8],rax
else if opcode?RG=66h
mov ax,rdx
mov[rsp+(counter?RD-1)*8],ax
else if opcode?RG=0FFh
mov eax,rdx
mov[rsp+(counter?RD-1)*8],eax
else
mov al,rdx
mov[rsp+(counter?RD-1)*8],al
end if
else if rdx eqtype 0
mov qword[rsp+(counter?RD-1)*8],rdx
else
mov[rsp+(counter?RD-1)*8],rdx
end if
end if
end if


if~[..arg?R5]eq
counter?RD=counter?RD+1
if counter?RD<=4
if[..arg?R5]eqtype 0
size@arg=8
else if[..arg?R5]eqtype byte 0
virtual at 0
mov[rbx],[..arg?R5]
; opcode?RH
load opcode?RH byte from 0
if opcode?RH and 0F8h=48h
size@arg=8
else if opcode?RH=66h
size@arg=2
else if opcode?RH=0C7h
size@arg=4
else
size@arg=1
end if
end virtual
else
virtual at 0
inc[..arg?R5]
; opcode?RI
load opcode?RI byte from 0
if opcode?RI=67h
load opcode?RI byte from 1
end if
if opcode?RI and 0F8h=48h
size@arg=8
else if opcode?RI=66h
size@arg=2
else if opcode?RI=0FFh
size@arg=4
else
size@arg=1
end if
end virtual
end if
if counter?RD=1
if size@arg=8
if~[..arg?R5]eq rcx
mov rcx,[..arg?R5]
end if
else if size@arg=4
if~[..arg?R5]eq ecx
mov ecx,[..arg?R5]
end if
else if size@arg=2
if~[..arg?R5]eq cx
mov cx,[..arg?R5]
end if
else if size@arg=1
if~[..arg?R5]eq cl
mov cl,[..arg?R5]
end if
end if
else if counter?RD=2
if size@arg=8
if~[..arg?R5]eq rdx
mov rdx,[..arg?R5]
end if
else if size@arg=4
if~[..arg?R5]eq edx
mov edx,[..arg?R5]
end if
else if size@arg=2
if~[..arg?R5]eq dx
mov dx,[..arg?R5]
end if
else if size@arg=1
if~[..arg?R5]eq dl
mov dl,[..arg?R5]
end if
end if
else if counter?RD=3
if size@arg=8
if~[..arg?R5]eq r8
mov r8,[..arg?R5]
end if
else if size@arg=4
if~[..arg?R5]eq r8d
mov r8d,[..arg?R5]
end if
else if size@arg=2
if~[..arg?R5]eq r8w
mov r8w,[..arg?R5]
end if
else if size@arg=1
if~[..arg?R5]eq r8b
mov r8b,[..arg?R5]
end if
end if
else if counter?RD=4
if size@arg=8
if~[..arg?R5]eq r9
mov r9,[..arg?R5]
end if
else if size@arg=4
if~[..arg?R5]eq r9d
mov r9d,[..arg?R5]
end if
else if size@arg=2
if~[..arg?R5]eq r9w
mov r9w,[..arg?R5]
end if
else if size@arg=1
if~[..arg?R5]eq r9b
mov r9b,[..arg?R5]
end if
end if
end if
else
if[..arg?R5]eqtype[0]|[..arg?R5]eqtype byte[0]
virtual at 0
inc[..arg?R5]
; opcode?RJ
load opcode?RJ byte from 0
end virtual
if opcode?RJ and 0F8h=48h
mov rax,[..arg?R5]
mov[rsp+(counter?RD-1)*8],rax
else if opcode?RJ=66h
mov ax,[..arg?R5]
mov[rsp+(counter?RD-1)*8],ax
else if opcode?RJ=0FFh
mov eax,[..arg?R5]
mov[rsp+(counter?RD-1)*8],eax
else
mov al,[..arg?R5]
mov[rsp+(counter?RD-1)*8],al
end if
else if[..arg?R5]eqtype 0
mov qword[rsp+(counter?RD-1)*8],[..arg?R5]
else
mov[rsp+(counter?RD-1)*8],[..arg?R5]
end if
end if
end if


argscount?RC=counter?RD
call[lstrcpy]
if stackspace?RB
add rsp,stackspace?RB
end if
;ret
;match any,{retn}
;match,{match epilogue:reglist,epilogue@proc:<regs?R1>
; \{ epilogue Function,flag?R0,parmbytes?R2,localbytes?R3,reglist \}}
;match epilogue:reglist,epiloguedef:<>
;{epilogue Function,flag?R0,parmbytes?R2,localbytes?R3,reglist}
;epiloguedef Function,flag?R0,parmbytes?R2,localbytes?R3,<>
;irps reg,{reverse pop reg}
if parmbytes?R2|localbytes?R3
leave
end if
if flag?R0 and 10000b
retn
else
retn parmbytes?R2
end if
;endp
;purge ret,locals,endl
;finish@proc
localbytes?R3=(current?R4+15)and(not 15)
end if
;purge finish@proc
;restore regs@proc
;match all,_String{restore all}
;restore _String
;restore args@proc
;match all,TempStr{restore all}
;restore TempStr

lstrcpy dq 0
    
From prepsrc


Last edited by LocoDelAssembly on 29 Jun 2009, 15:14; edited 1 time in total
Post 29 Jun 2009, 15:06
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8357
Location: Kraków, Poland
Tomasz Grysztar 29 Jun 2009, 15:11
It's not so hard to modify the existing one to do it. I leave it as an exercise to the reader (hint: rip a conversion routine from "prepsrc" tool). Wink If anyone makes such an alternative tool, I'll be happy to link it in the fas-tools thread

And using existing tools, you can use prepsrc and the assemble it again and make the listing. Wink Yes, I know that this is an overkill. Smile
Post 29 Jun 2009, 15:11
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 29 Jun 2009, 15:19
Quote:

you can use prepsrc and the assemble it again and make the listing.

I've just tried that but it doesn't remove the loads of assembler level code (I can know what is going to output by looking if it has a target address though).

OK, if you say it is easy I'll give it a try later then Smile
Post 29 Jun 2009, 15:19
View user's profile Send private message Reply with quote
shutdownall



Joined: 02 Apr 2010
Posts: 517
Location: Munich
shutdownall 02 Apr 2010, 16:41
I am working now a few weeks with FASM and I am quite happy with it.
Regarding some output listing I have following request.

Can you implement an automatic start of output listing when compiling asm project in FASMW.EXE ?
I thought about configuring this feature in options first but when I thought about it I would prefer using listing like use16 / use32 / segment statement in sourcecode.
So somebody can use this optional in his source code or not. Must be with option -a because in my current project only effective address (through org) is relevant not position in binary file.

Even better would be a feature to switch listing on and off for relevant parts if you have a long project.

I think adding a functional keyword for this would be helpful for many other users and purposes and maybe is not too much work. I would do myself if anybody can give a hint how to do. I am not willing to analyze the whole project. Rolling Eyes

Thanks, guys.
Post 02 Apr 2010, 16:41
View user's profile Send private message Send e-mail 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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.