I've got good news. It's easy :-). Bad news, it cannot be inlined in GCC (very predictable). VASM is pretty cool compiler, because it has HiSoft Devpac like syntax, so anyone who has coded with it in the past will be feeling like home and is well compatible with it. When incorporating m68k code we have several general use scenarios.

Use of variables from C/C++ code in m68k modules

You have to add XREF in m68k assembler source with label name found in C source prefixed with one underscore("_"). If C code is compiled as C++, then you have to put label into extern "C" {...}; section, otherwise there will be linking errors.

Use of external variables from m68k code in C/C++ modules

Firstly you have declare variable prefixed with underscore "_" (via standard ds.l/dc.l) and add XDEF with variable name in m68k source code.
After that you have to declare variable somewhere in C code as extern. If C code is compiled as C++, then you have to put label into extern "C" {...}; section, otherwise there will be linking errors. And that's it.

Invoking m68k assembler functions from C/C++ modules

If you have assembler function declared in you m68k asm source (prefixed with underscore "_") then you have to:
  • add XDEF function name to your assembler source, this will make label visible for other modules
  • add in C header function as extern without underscore and normal parameter list. If C code is compiled as C++, then you have to put label into extern "C" {...}; section, otherwise there will be linking errors due to different C++ name mangling scheme.
From now on you can use the function in your C/C++ programs.

Invoking C functions from m68k assembly code

You have to add XREF in m68k assembler source with label name of function found in C source prefixed with one underscore("_"). If C code is compiled as C++, then you have to put label into extern "C" {...}; section, otherwise there will be linking errors.
After that you can jump to soubroutine via standard jsr or bsr directive. If additional parameters are needed then you have to pass them via stack, return values are put in d0 register.

Linking troubleshooting

In case of linking problems you can check labels generated by compiler by running:
$ m68k-atari-mint-objdump -t my_gcc_object.o

or
$ m68k-atari-mint-nm my_gcc_object.o

This is very useful thing, C labels in general are prefixed usually with one underscore "_" if the labels are more complex then it means that you have compiled code as C++ code. C++ labels include additionally the return type and argument types of the function. To force compiler to C code generation you have to pass to CFLAGS the "-std=c99" or "-std=c89" parameter.
You have also to check if your variables are in global scope not the local one. C variables forwarded with "static" keyword aren't visible from external modules.
If C variables are modified outside of normal program flow then you have to add "volatile" keyword before their declaration. This is especially true if you are modyfying variables from exception handler.

Assembler flags used for compilation

Usually I'm invoking VASM in following way:
$ vasmm68k_mot source.s -Faout -quiet -x -m68000 -spaces -showopt -o output.o

The one drawback is that VASM can handle one source at time, you cannot input more source files and combine them into the one object file, but this is not problem at all.
The line above will compile GCC object file named output.o from source.s compatible with m68000 instruction set. All optimisations made by compiler will be outputted to console. Generated object file can be passed to gcc linker at later stages.