Yes indeed, but even more so: Forth is vastly more powerful than a mere macro assembler, because you have the full power of Forth to write arbitrary functions and mini-compilers to assemble code, no just simple macros! It comes with structured control flow constructs, and you can even write your own. Not only is the assembler itself written in Forth, but you can seamlessly extend and build on top of the it too, building high level interfaces and domain specific languages on top of low level assembly code and hardware.
Check out the amazingly powerful x86 assembler in OpenFirmware, which is deeply integrated with the hardware, operating system, bootstrapping, debugging, tracing, breakpointing, disassembling, cross assembling, meta compiling, and calling back and forth with C code:
purpose: x86 assembler
https://github.com/openbios/openfirmware/tree/master/cpu/x86
purpose: From Forth, call the C subroutine whose address is on the stack
https://github.com/openbios/openfirmware/blob/master/cpu/x86...
purpose: Tools for creating disembodied assembly code sequences
https://github.com/openbios/openfirmware/blob/master/cpu/x86...
purpose: Forth access words for special 386 registers
https://github.com/openbios/openfirmware/blob/master/cpu/x86...
purpose: After a breakpoint, displays a backtrace of C stack frames.
https://github.com/openbios/openfirmware/blob/master/cpu/x86...
purpose: 386 disassembler.
https://github.com/openbios/openfirmware/blob/master/cpu/x86...
purpose: Access to I/O ports and physical addresses under Linux
https://github.com/openbios/openfirmware/blob/master/cpu/x86...
https://github.com/openbios/openfirmware/blob/master/cpu/x86...
\ One of the very best features of FORTH assemblers is the ability
\ to use structured conditionals instead of branching to nonsense
\ labels.
: IF
>MARK swap
long-offsets @ if
dup h# eb = if
drop h# e9 asm8,
else
prefix-0f h# 10 + asm8,
then
real? if 0 asm16, else 0 asm32, then
else
ASM8, 0 asm8,
then
;
: THEN >RESOLVE ;
: BEGIN until
https://github.com/openbios/openfirmware/blob/master/cpu/x86... \ Some x86 assembler macros to make it easier to write x86 early
\ startup code. There are macros to set MSRs to specific values,
\ to set and clear individual MSR bits, to read and write PCI
\ configuration registers with the common CF8/CFC mechanism,
\ and to read and write I/O ports.
\ The code keeps the MSR register number in %ecx, the low 32 bits
\ of the value in %eax, and the high 32 bits in %edx, consistent
\ with the way the rdmsr and wrmsr machine instructions work.
\ The bitset and bitclr operations work on %eax, and the -hi versions
\ work on %edx.
\ The I/O port operations also leave the data in %eax, so you can
\ use bitset and bitclr with them too.