When working in a particular application domain you think in concepts of that
domain. For example, if you are developing software for lawyers you will work
and think in concepts such as: bill, statute, law, paragraph etc.
Execution platform, on the other hand, is where the software eventually run (a
physical or virtual machine). In that domain you have entirely different
concepts: stack, registers, instructions etc.
Someone, or something must translate a model of a solution from application
domain to the execution domain. The semantics gap is huge. General-purpose
languages (GPLs) alleviate the problem by using a higher level abstractions that
are easier to work with (e.g. classes, objects, methods, functions, parameters,
collections). So instead of translating the solution directly to the machine,
you translate it manually to the programming language, bridging the
specification gap, and the compiler mechanically do the translation to the
target machine (or many different machines) bridging the execution gap. Still a
lot of manual work in translating concepts from the application domain to GPL.
Domain-specific languages (DSL) go a step further. They are based on concepts
found in the application domain. Thus, the specification of the solution in DSL
should be easy 1:1 mapping. There is no gap between the application
domain and the specification. The DSL specification is now translated (usually
in multiple steps, e.g. DSL->GPL->machine code) to the target execution platform
mechanically.
For further reading on the topic of bridging the semantic gap, I suggest papers
on Language-Oriented Programming topic by Martin Ward and Sergey Dmitriev. To
read more on DSLs in general I suggest a book "DSL Engineering: Designing,
Implementing and Using Domain-Specific Languages" by Markus Voelter.