Skip to main content
gamedev.net
🔒 Locked

Creating new code at runtime

Started by antiquechrono Jul 4, 2007 at 3:52 PM 6 replies 1k views
Original Post
antiquechrono
antiquechrono
Let us pretend that we have a program that is able to create new code while it is being executed. The question I have is how would you get the newly generated code to acctually execute? My best guess would be to load the new code into a block of memory and use assembly to jump to that memory location. I would also guess that it would need to only try to run small self contained blocks of code at one time. How could branching code be handled since you do not know which block of code to generate until it is acctually run? How would you go about jumping back into the main program once each block has finished? Thanks in advance, and I hope this all makes sense :D
rip-off
rip-off
Possibly easier solution would be to use an embedded interpreter such as lua to interpret the generated code. Of course this depends on what you are doing... what *are* you doing anyway? [smile]
antiquechrono
antiquechrono
Quote:
Original post by rip-off
Possibly easier solution would be to use an embedded interpreter such as lua to interpret the generated code. Of course this depends on what you are doing... what *are* you doing anyway? [smile]


lol duh, that would help wouldn't it? I am going to attempt to write a dynamic binary translation NES emulator. Another term thrown around is dynamic recompilation although that really is not a correct description of what happens.
ToohrVyk
ToohrVyk
Put the code in something that can be dynamically loaded (a DLL, for instance) and load it.
DaBono
DaBono
I have no experience really with this, but my gut feeling say to handle branching code by just generating both paths of code, and using jmp to jump to the correct branch. That may get a bit different when the branch is between large blocks of code.
For jumping back to the main program, I'd guess you could structure the generated code as a function. So, push the main program address on the stack, run your code, then use ret to return to the main program.

As said, I have no experience, so maybe I'm missing something. One caveat that does spring to mind is that execution of 'data'-pages does trigger some security features of current systems. DEP (Data Execution Prevention) in Windows does that, and security-enhanced Linux kernels too.
Sneftel
Sneftel
If you're okay with GPLed code, you should check out GNU lightning, which simplifies and abstracts a lot of this stuff.
outRider
outRider
6502 instructions are very simple and the NES is very slow, you won't see much benefit at all from this sort of translation... if you don't already have a working, accurate emulator I'd do that before bothering with this... but I guess for learning purposes and future reference it's probably not too hard.

You're running along, fetching and interpreting 6502 instructions. You know that function calls are between jsr/rts pairs, so for each pair you encounter you make note of the jsr address (to uniquely identify the function) and you count how often each function is executed. After a while you'll have a decent histogram, so for the most frequently called functions you run your translator, which attempts to generate equivalent native functions.

You'll have to handle argument passing since your arguments will be on the emulated stack and not the native one, but there it is in a nutshell. Now, simply translating 6502 instructions one-to-one is a waste of time, your high-level interpreter will probably end up doing the same type of thing, you'll have to generate optimized native functions... but 6502 instructions are so simple that I doubt there's much you can do.

As for the details of how it's done, you'll have to do it in assembly. Allocate a block of memory, fill it with opcodes, and then later jump to it.
Anthony Serrano
Anthony Serrano
Quote:
Original post by outRider
You'll have to handle argument passing since your arguments will be on the emulated stack and not the native one, but there it is in a nutshell. Now, simply translating 6502 instructions one-to-one is a waste of time, your high-level interpreter will probably end up doing the same type of thing, you'll have to generate optimized native functions... but 6502 instructions are so simple that I doubt there's much you can do.


It's worth noting that since the 6502 doesn't have native stack-relative addressing modes and only has a 256-byte stack, and the NES is a platform on which every cycle counts, most arguments are passed either in registers (though only a small number can be passed like this) or in specific memory addresses, most frequently in the direct page ($0000 - $00FF), rather than being pushed onto the stack.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.