assemblystackparameter-passing68000easy68k

Pass a memory address by register


How do I pass a memory address from a register to other? My following routine receive the string memory address from stack (yes, it's necessary) and then try to put into D1 registers but it doesn't work and EASy68k emulator crash (or goes in an infinite loop?) when I try run this.

Code:

START ORG $1000


    MOVE.L T,D0
    MOVE.L D0,-(SP)
    BSR PRINTS



PRINTS:       
        MOVE.L D0,(SP)+
        MOVE.W D0,A1
        MOVE #14,D0
        TRAP #15
        RTS

T DC.B 'HELLO',0
    END START

UPDATE: I updated the way as arguments are pushed and poped from stack. Changed to use PEA instruction that looks like do exactly what I want to but it still doesn't work.

START ORG $1000
        PEA T(PC)
        *MOVE.L D0,-(SP)
        BSR PRINTS
        ADDQ.L #4,SP

    MOVE #9,D0       
        TRAP #15 

PRINTS:        
        MOVE 4(SP),A1
        MOVE #14,D0
        TRAP #15
        RTS

Solution

  • To get the argument onto the stack correctly, you either need to do:

        LEA    T,  A0
        MOVE.L A0, D0
        MOVE.L D0, -(SP)
    

    or

        PEA.L  T
    

    To get the argument off the stack correctly, you don't actually want to pop it in the called function. That's because BSR pushes a return address. Instead, you need to use indexed addressing as follows:

        MOVE.L (4,SP), A1  ; read argument from stack, overlooking return address
    

    And then to top it off, you need to "pop" the argument from the stack in the caller (not the callee), by adding this after the BSR instruction:

        ADDA.L #4, SP      ; remove argument from stack.
    

    The resulting program (which I did test in EASy68K), looks like this:

            ORG    $1000
    START:  
            PEA.L  T           ; push argument to stack
            BSR    PRINTS      ; call PRINTS; also pushes return address on stack
            ADDA.L #4, SP      ; remove argument from stack.
            SIMHALT
    
    PRINTS:
            MOVE.L (4,SP), A1  ; read argument from stack, overlooking return address
            MOVE.L #14, D0
            TRAP   #15
            RTS
    
    T       DC.B   'HELLO', 0
    
            END    START        ; last line of source
    

    And don't forget that SIMHALT ahead of PRINTS. You don't want to fall from your main code into your subroutines.

    Oh, and as you've likely discovered:

            PEA.L  T(PC)
    

    does work in place of

            PEA.L  T
    

    The main difference is code size. The first one uses PC-relative addressing to generate the address, while the second stores the full 32-bit address in the object code.