I need to transform 654321 into 654321321, using only DUP2_X1, POP, DUP_X2, POP2. I have a really difficult time with the DUP. Can anyone help?
I tried to go like this: 654321 DUP2_X1 654654321, then POP goes to 65465432, then DUP_X2 we'd have 6543265432... but I don't think I am doing them correctly.
So, basically you want to duplicate the last three elements of the operand stack while keeping all other elements intact and not use local variables nor heap space.
One sequence to achieve this would be
Instruction | Resulting Stack |
---|---|
(initial) | ...321 |
DUP2_X1 | ...21321 |
POP2 | ...213 |
DUP_X2 | ...3213 |
DUP_X2 | ...33213 |
POP | ...3321 |
DUP2_X1 | ...321321 |
A straight-forward program to test it using the ASM library looks like
package asm;
import static org.objectweb.asm.Opcodes.*;
import java.lang.invoke.*;
import org.objectweb.asm.*;
public class DuplicateThreeOperands {
public static void main(String[] args) throws ReflectiveOperationException {
final String s = "Ljava/lang/String;";
ClassWriter cw = new ClassWriter(0);
cw.visit(55, ACC_INTERFACE | ACC_ABSTRACT,
"asm/Test", null, "java/lang/Object", args);
MethodVisitor mv = cw.visitMethod(ACC_STATIC | ACC_PUBLIC,
"test", "()" + s, null, null);
mv.visitCode();
mv.visitLdcInsn("6");
mv.visitLdcInsn("5");
mv.visitLdcInsn("4");
mv.visitLdcInsn("3");
mv.visitLdcInsn("2");
mv.visitLdcInsn("1");
stackManipulation(mv);
mv.visitInvokeDynamicInsn("concat", "(" + s.repeat(9) + ")" + s, new Handle(
H_INVOKESTATIC, "java/lang/invoke/StringConcatFactory", "makeConcat",
MethodType.methodType(CallSite.class, MethodHandles.Lookup.class,
String.class, MethodType.class).toMethodDescriptorString(), false));
mv.visitInsn(ARETURN);
mv.visitMaxs(9, 0);
String result = (String)MethodHandles.lookup().defineClass(cw.toByteArray())
.getMethod("test").invoke(null);
System.out.println(result);
}
private static void stackManipulation(MethodVisitor mv) {
// ...321
mv.visitInsn(DUP2_X1); // ...21321
mv.visitInsn(POP2); // ...213
mv.visitInsn(DUP_X2); // ...3213
mv.visitInsn(DUP_X2); // ...33213
mv.visitInsn(POP); // ...3321
mv.visitInsn(DUP2_X1); // ...321321
}
}
and prints
654321321
You may look at the dup
instruction and following sections in JVM specification for further reference.