Assembly language is just a high level description of machine code: each assembler statement maps to one machine instruction. Those machine instructions are nothing but sequences of bytes. It is certainly possible to create executable code during runtime; you just write the appropriate bytes into a buffer, mark the buffer as executable, and jump in.
Back in the old days, before memory protection, we used to do all kinds of code-as-data-as-code tricks. I remember dynamically generating trampoline functions that effectively did partial application. I'd write a little stub of assembly code that would push a bunch of literal zeros onto a stack and then jump to zero; when I wanted to use it, I'd copy it, poke actual values into the literals, and then pass it along as a zero-parameters function pointer.
You don't change the language syntax; that doesn't really make sense in assembly world. It's more that assembly code lives in a world of bytes and pointers, and is itself very directly composed of bytes and pointers, and so it's as easy to use the same bytes-and-pointers concepts on code as it is on data.
This style still exists on microcontrollers, where there is generally no operating system. Instead, your compiler produces an image which you flash onto the controller chip. The controller has some startup sequence which jumps to some address in flash and runs. The chip's subsystems are controlled by registers located at specific addresses; in order to drive such a device you have to know how its address space is laid out, where your code is placed in it, and how your code interacts with the different types of memory and registers located in the address space.