News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Debugging a macro in MASM

Started by FellGleaming, January 25, 2021, 10:32:18 PM

Previous topic - Next topic

FellGleaming

Seems this should be a very easy question, but I can't find the answer by Googling.   I have some large macros in MASM that are fully-contained algorithm blocks.  When debugging (in Visual Studio 2019), I am unable to trace into these macros.  Example:

AlgoBlock MACRO Parm1, Parm2, Parm3
     (20-30 instructions)
ENDM

Main PROC
   ....
   AlgoBlock 1, 2, 3  <-- debugger will not step into this
   AlgoBlock 4, 5, 6
   AlgoBlock 7, 8, 9
   ret
Main ENDP

I probably need to do something along the lines of enabling opening a macro-expanded listing, but I can't get any further.  Thx for any help.

TouEnMasm


When debugging in source mode,the result depend only of the compiler and how .pdb and other files are made.
You can just try to insert an instruction to stop the debugger, like ,"mov eax,0".
Fa is a musical note to play with CL

jj2007

My largest macros are several hundred lines long, e.g. deb at 851 lines, so I know what you are talking about. The short answer is you can't debug them.

The long answer is "your debugger (e.g. Olly) will show you only the few lines of real code inserted by the macro". Which may wildly differ from what you thought to see.

One way to look at it is the listing, enabled by assembler option /Fl (see also .listall and .nolist in the MASM manual).

Another way is echoing what the macro does. Example:
Int64 MACRO arg ;   usage: movlps xmm0, Int64(0BBBBBBBBAAAAAAAAh)
Local tmp$
.DATA
  tmp$ QWORD arg
  % echo arg inserted in the data section
.CODE
  echo now exiting
  EXITM <tmp$>
ENDM


You can use that technique also for error messages:
is INSTR argC$, <shl 24>
ife is
tmp$ CATSTR <## line >, %@Line, <: first arg in RgbCol must be _alpha_ for Gdi+ pen ##>
% echo tmp$
.err
EXITM
endif


In this case, the macro stops the build and echoes to the output window ## line 123: first ... ##

To make debugging with Olly or similar easier, insert an INT 3:

int 3
inkey "where does this macro start and end?"
nops 8
int 3

Now you press F9 (in Olly) to run until the int 3 instruction, and you see immediately, thanks to 8 nop instructions, where your macro ended.

FellGleaming

Thanks for the replies -- jj2007 in particular seems to understand exactly the issue.  The problem in my case isn't the macro expansion itself though (that's fairly basic) but the actual algorithms, as they are heavily recursive and convoluted, so I really need to see the register values while single-stepping.

I found a partial solution on my own -- VS allows you to expand the assembly at a given point (I'd done this in HLLs before, but never tried it in ASM) by using the Ctrl-K,G chord.   This shows you the macro expansion, though without symbolic imformation of course, just raw assembly.   I'm going to experiment with jj2007's suggestion to look at the listing files -- there may be some way to have the debugger load them for trace-level debugging with symbolic info.

jj2007

Quote from: FellGleaming on January 26, 2021, 02:07:12 AMI really need to see the register values while single-stepping.

Check the deb macro, it's part of MasmBasic:
include \masm32\MasmBasic\MasmBasic.inc ; use instead of masm32rt.inc
.data
TwoQwords dq 1234567890abcdefh, 2222222222222222h
OneOword OWORD ?
.code
start:
  mov ecx, chr$("a string")
  mov eax, offset start
  movups xmm0, TwoQwords
  movups OneOword, xmm0
  fldpi ; long live the FPU!
  mov ebx, 1234567890
  or eax, -1 ; set the sign? flag
  deb 4, "Registers and flags remain intact", x:eax, ebx, $ecx, x:xmm0, x:OneOword, ST(0), flags
  deb 4, "... as you can see", x:eax, ebx, $ecx, x:xmm0, x:OneOword, ST(0), flags
  mov ecx, 15
  .Repeat
PSLLDQ xmm0, 1
deb 6, "Shifting", x:xmm0 ; the "6" means show only the first 6 results
dec ecx
  .Until Sign?
  exit
end start


Output:
Registers and flags remain intact
x:eax           FFFFFFFF
ebx             1234567890
$ecx            a string
x:xmm0          22222222 22222222 12345678 90ABCDEF
x:OneOword      22222222 22222222 12345678 90ABCDEF
ST(0)           3.141592653589793238
flags:          czSo

... as you can see
x:eax           FFFFFFFF
ebx             1234567890
$ecx            a string
x:xmm0          22222222 22222222 12345678 90ABCDEF
x:OneOword      22222222 22222222 12345678 90ABCDEF
ST(0)           3.141592653589793238
flags:          czSo
Shifting        x:xmm0          22222222 22222212 34567890 ABCDEF00
Shifting        x:xmm0          22222222 22221234 567890AB CDEF0000
Shifting        x:xmm0          22222222 22123456 7890ABCD EF000000
Shifting        x:xmm0          22222222 12345678 90ABCDEF 00000000
Shifting        x:xmm0          22222212 34567890 ABCDEF00 00000000
Shifting        x:xmm0          22221234 567890AB CDEF0000 00000000

mineiro

You can transform a macro into a procedure and after debug that program.
Put global variables instead of local variables just for test. Forgot now options to create simbolic debug.

AlgoBlock proc Parm1, Parm2, Parm3
     (20-30 instructions)
AlgoBlock endp

Main PROC
   ....
int 3h          ;debugger will stop here if you run your program, a breakpoint
                ;depends of your debugger, some will jump to next instruction and pause
                ;others will stop at int 3h address, so you need select next instruction and step from here
                ;or you can change ip/eip/rip address by hands.
invoke AlgoBlock 1, 2, 3
nop             ;no operation
invoke    AlgoBlock 4, 5, 6
nop
invoke    AlgoBlock 7, 8, 9
ret
Main ENDP

I'd rather be this ambulant metamorphosis than to have that old opinion about everything

daydreamer

Quote from: FellGleaming on January 26, 2021, 02:07:12 AM
Thanks for the replies -- jj2007 in particular seems to understand exactly the issue.  The problem in my case isn't the macro expansion itself though (that's fairly basic) but the actual algorithms, as they are heavily recursive and convoluted, so I really need to see the register values while single-stepping.

I found a partial solution on my own -- VS allows you to expand the assembly at a given point (I'd done this in HLLs before, but never tried it in ASM) by using the Ctrl-K,G chord.   This shows you the macro expansion, though without symbolic imformation of course, just raw assembly.   I'm going to experiment with jj2007's suggestion to look at the listing files -- there may be some way to have the debugger load them for trace-level debugging with symbolic info.
debugger have different tabs for different kind of data to keep track of below in the debugger window,autos: is most current registers variables,locals:local variables...
rightclick and you can switch between hexadecimal or decimal showing values,hexadecimal is easier when you wanna know if logical AND,OR,XOR,NOT works correctly

I think you also can move over different variables and registers in edit source code while debugging and you can see their values
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

FellGleaming

Some great info here, thx for all the replies.  I am poring over the documentation for MasmBasic now, it looks like it will be very helpful in the long run.