5 ms·
Writing a self-modifying x86 factorial program
- 0x0 5y agoDoesn't self-modifying code cause massive cache flushes and stalls on modern x86 archs?
- ghusbands 5y agoNot even that modern. The self-modifying code in the article would be slow even on chips produced in the 1990s.
- colejohnson66 5y agoAny processor using pipelines suffers from self modifying code. The Intel 80486 was the first x86 chip to have a pipeline, and it was released in April 1989(!). Granted, it only had a 5 stage pipeline, so you'd only lose a few clocks each time, but modern x86 architectures have pipelines dozens of stages deep.
- unnouinceput 5y ago>>This is quite simple, if it needs explanation then this isn’t for you. It's for me, because you can definitely do one less loop by modifying: cmp ebx, 0 to cmp ebx, 1
- jonsen 5y ago> ; could exit at 1, but then it doesn't handle 0x2
- unnouinceput 5y agothat's a comment for another variant. For this, at beginning, it could simply stop at 1
- idiocrat 5y agoYou do not need the "cmp ebx, ..." because "sub ebx, 1" already sets the zero flag.
- FastEatSlow 5y agoThanks, I forgot about that
- FastEatSlow 5y agoThere was an edge case where when the input was 0x2, it returned 0x1, that was my quick way of handling that.
- unnouinceput 5y agoLet's see, step by step, if we put 2 in EAX what happens: Init: EBX = 2; EAX = 2; Loop: EBX = 1;//gets decremented CMP EBX, 1;//it's 1 so we exit Final result is 2. Sounds the edge case is not that of an edge after all
- ghusbands 5y agoAlso, if we're to be pedantic about the code across the article, if they used dec (directly on memory) rather than sub, in the self modifying code, they wouldn't need a load/sub/store sequence. The zero flag would still be appropriately modified.
- FastEatSlow 5y agoThanks, I forgot about dec.
- magicalhippo 5y agoMisread it as "factorio program", and was quite excited someone had ported an x86 emulator to Factorio...
- snickerer 5y agoI am wondering: Does it make sense to write self-modifying code not for obfuscation but for optimization? Can we have such code to speed up calculations in a way that is not possible with static code? Does anybody know? I would be very interested in an example.
- deleted 5y ago[deleted]
- FastEatSlow 5y agoIt doesn't really, a NOP is equivalent to most jumps now, I'll try to dig up a source for that in a few hours. It used to be the case 10-20 years ago, I remember reading about it on an llvm thread.
- neel_k 5y agoSelf-modifying code was useful for optimisation back in the 80s, but these days it's usually awful for performance (with JIT compilation as the main exception to this rule). Your CPU has an instruction cache and a data cache, and on ARM (and x86, too, but I'm not sure) these caches are not coherent. So if you modify your instruction stream with a write, you have to clear the instruction cache to ensure that your modified instructions are actually executed by the processor. If you do this a lot, this will make things S-L-O-W, because it forces you to go all the way to main memory to find the next instruction to execute. This means that if you do want to generate code at runtime, you want to batch the modifications into large groups, so that you have to invalidate the i-cache less frequently. This actually is useful -- it's what JIT compilation is! The reason that JIT can be helpful (even in statically typed languages like Java or Haskell) is that programs often get passed functions as arguments (eg, qsort in C). A static compiler can't optimise these functions much, because you have to know what the function argument will be to do much. But at runtime, you do know what the function is, and by inlining it your code can be made much faster.
- gpderetta 5y agoInlining passed function pointer is not really a JIT only optimization. As long as the pointer is a constant it only requires interprocedural optimizations and/or link time optimization. The jit can help if the value of the pointer varies dynamically and in an unpredictable way (otherwise PGO would also help).
- kple 5y agoadventofcode.com did something like this last year (or two years ago?)