So I know the very basics, that a compiler turns source code into assembly code and an assembler turns assembly code into machine code. What I haven\'t been able to google p
You are overcomplicating this. A compiler takes text in some format and converts it, typically, to text in another format. Say for example a C compiler turns C into assembly. A compiler is just a program, nothing special about it just like your web browser is a program, the text editor you use for writing the programs is just a program, the command line/console if you use one is just a program. No magic.
An assembler is just a program that takes text in and typically outputs some form of binary file. There are many formats just like there are many binary formats for images and videos (bmp, jpg, png, gif, tiff, m4v, mpeg, etc). No magic, just a program that does a job like any of the ones listed above.
Same goes for the linker, it takes binary files in and typically outputs a binary file out.
These programs are, typically, like all other programs on your hard drive, or at least on a drive you have mounted and can access. Like the web browser and text editor, etc. Now to run them you need them "in the path" ideally or if part of some IDE then the IDE might not need them in the path it may know relative to itself where they are. Likewise the compiler which often calls the assembler and linker for you, might not need the path it may know/assume relative to where it is where they are. But they live on the file system like any other program/file but to execute them they need to be able to be found. And depending on the operating system and the installer for the toolchain there are often different choices and not one global rule.
There is no reason why you cant have as many different compilers and assemblers as you can fit on your filesystem, they are just programs like any other, so you have to find a place for them and have to have a way to run them. There is no reason to assume that any two compilers produce the same binary from the same source code, likewise there is no reason to assume that any assembler is able to assemble the output of any compiler. That is where the term toolchain comes from, a set of tools that link together in a chain, compiler outputs something the assembler in the toolchain knows how to deal with the assembler outputs something the linker knows how to deal with. You might have some cross compatibility among different toolchains/vendors, but that doesnt mean they have to that could either be by design, or dumb luck.
Let's avoid the details and assume that the excution process is so easy (compilation=>assmbly=>CPU) to answer your main question : a compiler and an assembler are both programs (depending on your CPU architecture) so you could install them or choose the buit in with the system
For exemple in Gnu/linux systems : gcc is a compiler Nasm is an assembler
they are located on your hard drive for exemple under : /usr/bin/
an assembler can use CPU interuption and syscalls so he coud use the kernell to talk to the cpu to perform much complex actions.
you could use any compiler or assembler from this list (https://en.wikipedia.org/wiki/Comparison_of_assemblers) but keep in mind you should respect which architecture are you using ARM X86 X64 AMD..