7

According to the DCPU specification, the only time a SET instruction fails is if the a value is a literal.

So would the following work?

SET [PC],0x1000

A more useful version would be setting an offset of PC, so a rather strange infinite loop would be:

SET [PC+0x2],0x89C3 ; = SUB PC,0x2
Charles
  • 50,943
  • 13
  • 104
  • 142
Matt
  • 7,100
  • 3
  • 28
  • 58

2 Answers2

7

Probably (= I think it should work but I didn't try).

This is called "self modifying" code and was quite common the 8bit era because of a) limited RAM and b) limited code size. Code like that is very powerful but error prone. If your code base grows, this can quickly become a maintenance nightmare.

Famous use cases:

  1. Windows 95 used code like this to build graphics rendering code on the stack.
  2. Viruses and trojans use this as an attack vector (write code on the stack or manipulate return addresses to simluate a JMP)
  3. Simulate switch statements on the C64
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • The only difference that I can see is that you can't execute code on the stack with DCPU, since `PC` values are in a completely different memory space to the stack/ram, so `SET PC,###` cannot be made to jump onto the stack. – Matt Apr 05 '12 at 15:44
  • @Mat - You can execute code on the stack with DCPU. Take a look at the very bottom of the DCPU specification. The memory dump of that code. – flumpb Apr 05 '12 at 17:46
  • @kisplit, You can put code on the stack, but how do you jump to it? That dump is just the executable code. – Matt Apr 05 '12 at 18:27
  • 1
    @Mat - SET PC, 0xFFEF. And say I want to jump to the start of my program again: SET PC, 0. Now say I have instructions that write data to 0x1000-0x10F0. I can execute that too with: SET PC, 0x1000 – flumpb Apr 05 '12 at 18:40
  • So you are saying that the code is stored in the ram? I know how to jump, but my understanding of DCPU is that the two are in different memory spaces – Matt Apr 05 '12 at 19:12
  • @Mat SP starts with a value of 0xFFFF, as written in the spec: By using 0x18, 0x19, 0x1a as POP, PEEK and PUSH, there's a reverse stack starting at memory location 0xffff – Kevin Coffey Apr 05 '12 at 23:58
  • @kisplit, Ok. That's the main thing I was trying to get my head around. As an assembly programmer, I'm used to having sections, which can be labeled as read-only. – Matt Apr 06 '12 at 14:48
  • @Mat - Heh, on windows and linux it's easy to turn those pages as writable. VirtualProtectEx comes to mind – flumpb Apr 06 '12 at 14:52
  • 1
    @KevinCoffey minor nit, but SP actually starts at 0x0000, it's just a PUSH decrements SP before writing to [SP] so it's 0xFFFF at the time of first write. – James Tauber Apr 07 '12 at 07:44
4

There's no value for [PC], so I'm guessing you need to do it in a round-about way by storing PC in something you can use as a pointer (registry or memory).

        SET  A , PC
        SET [A+3], 0x8dc3 ; SUB PC, 3 (if A can't be changed from outside SUB PC,2 works too.)
Piotr
  • 41
  • 1
  • That code wouldn't work, as the code section uses the same numbers as the ram/stack. `A` after that statement would evaluate to a number, and then `[A+3]` would refer to that position in memory, rather than in the code section. – Matt Apr 05 '12 at 17:36
  • 1
    @Mat - There are no separate sections. You can write self modifying code with DCPU. – flumpb Apr 05 '12 at 17:48