0
votes

I was wondering how I could POP a variable off the stack and store it in a register. For example:

asm(" MOV R5, #10");
asm ("MOV R6, #20");
asm("PUSH {R5,R6}");

I now want to POP the variables off the stack and store the value of R6 in R5 and vica versa. I have searched the ARM site (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204j/Babefbce.html) but I can't find a valuable answer. I hope someone could help me.

EDIT:

I figured this would do the job:

  asm("MOV R5, #10");
  asm("MOV R6, #20");
  asm("PUSH {R5,R6}");
  asm("POP {R5,R6}");

But the registers do not change according to my debugger.

3
You want to swap them. Try to push and pop them individually. - auselen
Where is the value stored when I pop it? - Niels Robben
to the registers you put in the list, like pop {r4, r5} - auselen
the answers to your question are on the arm site you mentioned, the architectural reference manuals describe the instruction set in great detail, how push works and how pop works. - old_timer

3 Answers

2
votes

The problem you are encountering is that when multiple registers are specified in a PUSH or POP they are always pushed or popped in numerical order. The order that they are specified in the instruction does not matter. The only way to force the register contents to be swapped in this manner is to perform one of the operations (either the push or the pop) on the two registers individually, in two separate instructions. You will need to check the documentation for the PUSH and POP instructions to determine the default order used when handling multiple registers, and then intentionally reverse that order using two separate instructions.

2
votes

push and pop are both pseudo-instructions.

They are translated to stm and ldm respectively at assembly time, the suffix depending on the stack type (full descending being the de-factor standard) :

  • full descending : stmdb, ldmia
  • full ascending : stmib, ldmda
  • empty descending : stmda, ldmib
  • empty ascending : stmia, ldmdb

And a very simple rule applies : lower numbered registers load/store the value from/to the lower addresses.

It's impossible to alter the way it works. If you want to push the values in a different order than the rule says above, either sort prior to pushing, or push them separately in an order you see it fit like :

push {r6}
push {r5}

Honestly, I don't see any good reason for doing this. If you absolutely need this kind of "sorting", ask yourself first whether you aren't doing something wrong.

0
votes
  asm("MOVS R5, #10");
  asm("MOVS R6, #20");

  asm("PUSH {R5,R6}");
  asm("POP {R6}");
  asm("POP {R5}");

I have fixed the problem now, I was completely new to this, and the answer turns out to be very straight forward. Thanks everyone for their time.