You compile the stack based code into register code. It is, of course, easier to say than to do, but it is within the range of a skilled team, not absurdly complicated.
You can think about it on a really small scale:
PUSH 1
PUSH 2
PUSH 3
ADD
PUSH 4
MULT
ADD
is not that hard to conceptually rewrite into
STORE 1, r1
STORE 2, r2
STORE 3, r3
ADD r2, r3 INTO r2
STORE 4, r3
MULT r2, r3 INTO r2
ADD r1, r2 INTO r1
Of course, from there, you have to deal with running out of registers, then you're going to want to optimize the resulting code (for instance, generally small numbers like this can fit into the opcodes themselves so we can optimize away all the STORE instructions easily in most if not all assembly languages), but, again, this is all fairly attainable code to developers with the correct skills, not pie-in-the-sky stuff. Compiler courses do not normally deal directly with this exact problem, but by the time you finish one you'd know enough to tackle this problem since the problem since the problem that compiler courses do deal with is a more-or-less a superset of this problem.
oh okay, so you're not really running the original byte code. You're cross-compiling it to a different architecture effectively. That makes sense then!
You can think about it on a really small scale:
is not that hard to conceptually rewrite into Of course, from there, you have to deal with running out of registers, then you're going to want to optimize the resulting code (for instance, generally small numbers like this can fit into the opcodes themselves so we can optimize away all the STORE instructions easily in most if not all assembly languages), but, again, this is all fairly attainable code to developers with the correct skills, not pie-in-the-sky stuff. Compiler courses do not normally deal directly with this exact problem, but by the time you finish one you'd know enough to tackle this problem since the problem since the problem that compiler courses do deal with is a more-or-less a superset of this problem.