0

I have the following C code:

/* ctsw.c : context switcher
 */

#include <xeroskernel.h>

void _ISREntryPoint();
static void *k_stack;
static unsigned long *P_ESP;
static unsigned long *ARGS;

void contextinit() {
  set_evec(59, (long) _ISREntryPoint);
}

int contextswitch( pcb *p ) {
  P_ESP = p->esp;
  int retval = p->retval;
  __asm __volatile("pushf\n\t"
                   "pusha\n\t"
                   "movl %%esp, k_stack\n\t"
                   "movl P_ESP, %%esp\n\t"
                   "movl retval, 28(%%esp)\n\t"
                   "popa\n\t"
                   "iret\n\t"
                   "_ISREntryPoint:\n\t"
                   "    pusha\n\t"
                   "    movl %%esp, P_ESP\n\t"
                   "    movl 44(%%esp), ARGS\n\t"
                   "    movl k_stack, %%esp\n\t"
                   "    popa\n\t"
                   "    popf\n\t"
                   :
                   :
                   : "%eax"
                   );
  p->esp = P_ESP;
  p->args = ARGS + 1;
  return *ARGS;
}

It is giving me the following compile error:

../c/ctsw.c: Assembler messages:
../c/ctsw.c:21: Error: too many memory references for `mov'
../c/ctsw.c:26: Error: too many memory references for `mov'

What am I doing wrong? How do mov register values to static variables and vice versa? Thanks

b_pcakes
  • 2,312
  • 3
  • 25
  • 42
  • Are you doing this to learn asm, or are you trying to actually do something useful? If the latter, use a input operand: see [the end of this answer for links to guides](http://stackoverflow.com/questions/34520013/using-base-pointer-register-in-c-inline-asm/34522750#34522750), and other links from the [inline-assembly tag wiki](http://stackoverflow.com/tags/inline-assembly/info). – Peter Cordes Oct 08 '16 at 01:44
  • @PeterCordes I am learning. And it is not a dupe at all, read the other question and tell me how it answers this question. Sure, it is the same error, but not for the same reason – b_pcakes Oct 08 '16 at 01:53
  • 1
    This inline assembly has serious issues, but the specific error you are getting is related to `movl retval, 28(%%esp)` and `movl 44(%%esp), ARGS` . The problem is that both destination and source are memory operands. x86 doesn't allow 2 memory operands on a single `mov` instruction. You'd could move one to a temporary register and then the contents of the register to the destination. – Michael Petch Oct 08 '16 at 02:17
  • It's exactly the same issue. ARGS is a memory operand, so if you want to copy from `44(%%esp)` to it, you need to load into a register and then store to ARGS, like the answers on the duplicate question say. I stopped looking for other dups after seeing that the answer there was exactly what you needed. – Peter Cordes Oct 08 '16 at 02:25
  • I see, fixed that now. How would I move c local variables into a register without extended assembly? is this possible? – b_pcakes Oct 08 '16 at 02:27
  • 1
    It is possible but it is fugly (I recommend not doing it) as you should use proper input and output constraints to achieve it. https://gcc.gnu.org/onlinedocs/gcc/Explicit-Register-Variables.html – Michael Petch Oct 08 '16 at 02:32
  • 1
    I totally agree with Michael: you should always use input/output operands for inputs/outputs from inline-asm statements. Then you don't need a `"memory"` clobber to tell the compiler you might have modified anything / everything. Asking the compiler for a variable already in a register avoids making the compiler store it to memory for you to reload, if the compiler already had it live in a reg. See the link in my first comment to learn how to write GNU C inline asm that doesn't result in wasted instructions from the compiler's code + yours. – Peter Cordes Oct 08 '16 at 02:39

0 Answers0