While security is – of course – a noble cause, this approach has many uses beyond that.
E.g., I just upgraded an old 6502 assembler to support complex value expressions, including variables. Now, the 6502 has two distinct address modes for accessing memory (r/w), a fast single-byte mode dedicated to so-called zero-page addresses (like 0x0020), and a normal one for word-size address operands. (The "zero-page" may be regarded as a bank of 256 auxiliary registers.)
A good assembler should determine the address mode automatically, and, at the same time, should provide means to express the wish for a value to be treated as a word-size address. A common convention is to assume numbers expressed like "0x0020" to be of word-size, while "0x20" would be of byte-size. Using complex expressions, we want to propagate this kind of "tainting" to any derived values, as well. It's basically the same problem, in this case propagating from the parsing level to any evaluations while using just a binary attribute. At the same time, as we have to determine the size of any instructions in a first pass, in order to have known addresses ready for the second pass, which actually generates the object code, it's somewhat similar to the problem of assuring correctness at compile time.
There are lots of real-world problems involving any kind of parsing, where an approach like this is help- and useful.
E.g., I just upgraded an old 6502 assembler to support complex value expressions, including variables. Now, the 6502 has two distinct address modes for accessing memory (r/w), a fast single-byte mode dedicated to so-called zero-page addresses (like 0x0020), and a normal one for word-size address operands. (The "zero-page" may be regarded as a bank of 256 auxiliary registers.)
A good assembler should determine the address mode automatically, and, at the same time, should provide means to express the wish for a value to be treated as a word-size address. A common convention is to assume numbers expressed like "0x0020" to be of word-size, while "0x20" would be of byte-size. Using complex expressions, we want to propagate this kind of "tainting" to any derived values, as well. It's basically the same problem, in this case propagating from the parsing level to any evaluations while using just a binary attribute. At the same time, as we have to determine the size of any instructions in a first pass, in order to have known addresses ready for the second pass, which actually generates the object code, it's somewhat similar to the problem of assuring correctness at compile time.
There are lots of real-world problems involving any kind of parsing, where an approach like this is help- and useful.