Info: it the most difficult current programming language, though not the most difficult possible one. Malbolge, for those not familiar with it, is a language designed to be have so far have expressed an interest in programming in Malbolge!. Malbolge is a programming language invented by Ben Olmstead in , named after the eighth circle of hell in Dante’s Inferno. The name was.
|Published (Last):||23 March 2009|
|PDF File Size:||1.51 Mb|
|ePub File Size:||4.60 Mb|
|Price:||Free* [*Free Regsitration Required]|
The Malbolge language has eluded many attempts to use it for some years. That was before Lou Scheffer published his cryptanalysis of the encryption algorithm it uses. This article walks the way he opened, explaining many of his findings in detail and other caveats that must be taken into account not mentioned by him. Malbolge’s probably biggest piece of evilness comes from the encryption of instructions as they are executed.
That encryption, fortunately, has a few weaknesses that make writing Malbolge programs feasible. In the case of the jump instruction, whose execution has the effect of changing the value of the code pointer C in step 2 above, the memory position that gets encrypted via step 3 is the final value of the code pointer, i.
That’s a great advantage as we will see later.
Another weakness that can be exploited is the existence of length-2 cycles in the encryption step. Every possible instruction can be written as a malbolte in which the other instruction in the cycle is a NOP, ,anguage is, when an instruction is executed it turns into a NOP and when that NOP is executed it turns into the original instruction.
Here’s a table of these memory addresses modulo 94 allowing period-2 instructions where the second is a Prograjming, together with the instruction itself there are exactly two possible addresses for each of these instructions, so both are listed:.
The remaining three instructions are irrelevant here: The last weakness that makes it practical to write Malbolge programs is the existence of at least one immutable NOP for every possible memory address.
However very few addresses allow to directly enter immutable NOPs into the code because the range of allowed values in the source code is very limited. Note the distinction between the o instruction and any of the other NOPs: Both can be immutable NOPs, though, depending on the address.
The following addresses modulo 94 allow to directly enter an immutable NOP into the code by using the o instruction:. In memory addresses other than these the o NOP instructions will mutate into a non-NOP instruction after a variable number of executions.
For example, an o executed at position 0 modulo 94 will become a j after 29 executions. The values 70 and 74 form the 2-cycle: They are immutable NOPs for most addresses modulo The following table lists all the addresses that are an exception to this rule, together with sample values which are immutable NOPs for them:. The importance of immutable NOPs can easily be seen by realizing that the data pointer D is incremented with every instruction executed, just as the code pointer, so in order to position the data pointer as required it’s sometimes necessary to advance it by inserting NOP instructions in the code.
Let’s assume we want to execute the following code as in the cat program:. Easy as it looks, it’s not so easy to write in Malbolge.
To start with, this must be translated to the following:. Since the instructions are at addresses which form a 2-cycle, in the first execution all instructions will perform their function while in the second they will act as NOPs, then the cycle will start again. Crazy as it is, the crazy operator can be very useful. At a minimum it provides a mechanism for storing values into memory, which is necessary for almost any operation except the most basic ones as the above.
For example, checking for EOF before printing the character is not possible without using at least a partial version of the store operation, because there’s no way to examine the contents of the accumulator without altering it. It has to be made in several steps. This can be done in this way:. The store of the accumulator A into memory now consists of two steps: Note that this method makes it necessary to perform the above 3 steps into just another memory address.
That’s part of the fun of writing Malbolge programs. There are two simple ish ways of loading a value from memory into A ; a straightforward one is to perform ten rotates, but this is very costly. There’s another one using the crazy operator: After these operations the accumulator will hold the value originally present in that address.
Malbolge programming – Esolang
Now that we’ve reached the point where Scheffer stops let’s continue from there, pointing out the problems that are encountered on the way. For now we’ll assume that the memory can be preloaded at will, even if that’s not the case. The first point to note is that step 5 can’t be performed every two cycles: The solution to this problem is to revert the j instruction at step 5 just after it’s executed.
The way of doing this is to re-execute or “pseudo-execute” it a pseudo-execution means to jump to the instruction immediately following it, so that the encryption step is performed on it anyway. We add a step 5b executed after step This will complete the simplified version of the cat program. The design involves working with both the data and the code section at the same time, keeping track especially of the value of the D register, as follows the choice of 97 as the start of the data area is arbitrary:.
Remember that both C and D are incremented between steps, and that the final value of C prior to the increment is the position that gets encrypted. This will loop forever; every two iterations it will input a byte and output it, and execute two NOPs at the next iteration.
Now it should be apparent that it’s possible to achieve execution of arbitrary code by means of jumping to the places where the instructions are to be executed, but there are still a few problems that need to be addressed: We’ve assumed that the memory can be preloaded at will, even if that’s not the case. Because it’s possible in principle to create an initialization routine that is executed only once, with no loops or repetitions, so that there’s no need to care about self-encryption.
That routine’s mission is to set up the memory just as needed. The problem is that the routine can be very expensive in terms of number of instructions used: Fortunately it’s much easier in Malbolge to write execute-once code than reusable code. As we’ve explained things, it’s not possible to reuse an instruction which already has the desired number of immutable NOPs around it in the same turn of the main loop, because the second time it’s executed it acts as a NOP.
This means that either of these two approaches has to be taken: The second approach is by far the most desirable one because it means just one extra program pointer per instruction, while the first one implies initialization of lots of immutable NOPs and allocation of many extra instructions.
So we add one extra word of overhead to the ones already stated:. Now it may be more apparent why the approach of making ten rotate operations for one load was not the preferred one, as that would mean ten times the overhead explained above plus the initialization of it all.
Here’s an example of a subprogram that stores the accumulator into a memory position, for the purpose of illustrating how the influence of the overhead mentioned above applies to Malbolge programs. Please note that the code is untested and there might be bugs; it’s more an example than anything else. It’s possible to reduce the total size, but not much.
The code pointers use labels while the data addresses are expressed numerically. All instructions except i are assumed to be length-2 cycles. The labels for code pointers represent the address of the memory word prior to the address where the label points to. Thus, code pointers with this prefix directly point to the command’s address instead of the memory word before the command. In general, special care must be taken to ensure that the address prior to the target of a jump always contains a character in the printable ASCII range or the reference interpreter may crash.
Execution starts with data register pointing to address Instead of controlling the program flow with the code register, which means that all commands are written in their correct order filled with immutable NOPs, it is possible to control the program flow using the data register.
This technique has been developed by Hisashi Iizawa et al. Using this technique every instruction in Malbolge except Jmp will only occur once in the whole program at a position where the encryption function has a 2-cycle, followed by a Jmp instruction there may be some exceptions, but this is the basic idea.
Thus we know that after the execution of every instruction a Jmp instruction will follow. The next data word will be a pointer to another Malbolge command, e. When we control the program flow with the D register, branches can be executed by MoveD.
If we use a MoveD instruction with a 2-cycle of the encryption function without a restore operation, we can build a loop that will be executed two times. Using this technique it’s possible to save many immutable NOPs, so the number of cells that have to be initialized decreases dramatically. Simple programs in Malbolge still need many memory cells. However, with this technique programs like a cat that halts on EOF are possible. Programming with memory addresses is very confusing, and it may be time-consuming to manually write code in Malbolge to initialize the memory cells that are needed.
To avoid this one can use a Malbolge assembler. Such an assembler can be found in the external resources: One of the examples is a cat program that halts on EOF.
We just introduced a Malbolge assembly language and got rid of absolute positions for code or data sections. Thus, the code above can be extended easily.
A Malbolge program can be created from the assembly program above as follows.
We must choose positions of code and data sections, replace labels by the address of the memory word prior to the address where the label points to, and write use-once Malbolge code to initialize everything. However, one may use a Malbolge assembler in malbolg to automatize this process. Retrieved mxlbolge ” https: Navigation menu Personal tools Create account Log in. Views Read View source View history. This page was last edited on 21 Julyat Content is available under CC0 public domain dedication.