2010-04-09 101 views
4

當您將參數傳遞給CPU堆棧上的函數時,您將參數放在上面,然後JSR將返回地址放在堆棧上。 所以,在你的函數意味着你必須把堆棧(返回地址) 的頂部項目之前,你可以走別人關)在堆棧上傳遞參數

返回值按照慣例存儲在寄存器D0

例如如下去做正確的方法:

... 
|Let’s do some addition with a function, 
MOVE.L #4, -(SP) 
MOVE.L #5, -(SP) 
JSR add 
     |the result of the addition (4+5) is in D0 (9) 
... 

add: 
    MOVE.L (SP)+, A1  |store the return address 
          |in a register 
    MOVE.L (SP)+, D0  |get 1st parameter, put in D0 
    MOVE.L (SP)+, D2  |get 2nd parameter, put in D2 

    ADD.L  D2, D0  |add them, 
          |storing the result in D0 
    MOVE.L A1, -(SP)  |put the address back on the 
          |Stack 
    RTS      |return 

回答

6

編號

被調用者(目標函數)通常不負責刪除自己的參數。來電者把它們放在那裏,並且是最懂得如何去除它們的人。

而在68000上,使用堆棧中的相對偏移量很容易讀取,因此不需要從堆棧中物理刪除(彈出)參數。這就解決了必須很好地「雙緩衝」返回地址的問題。

所以,你的代碼應該讀這樣的事情:

MOVE.L #4, -(SP) 
    MOVE.L #5, -(SP) 
    JSR add 
    ADDQ.L #8, SP   |remove the arguments from the stack, both at once. 

... 

add: 
    MOVE.L 4(SP), D0  |get 1st parameter, put in D0 
    ADD.L 8(SP), D0  |add the 2nd parameter 
    RTS      |return 
8

你不從棧「起飛」的參數,因爲你不彈出他們的感覺。您通常會指定一個幀寄存器指向過程入口點處的堆棧頂部,並從幀指針以恆定的已知偏移量訪問參數。然後,您的索引只是「跳過」返回地址,您知道該地址在那裏。

E.g.在一些假設的程序集中,當你在一個程序中。假設堆棧增長了下來:

... 
argument2 
argument1 
ret addr  <---- stack pointer 

所以只要訪問argument1在偏移sp+4(假設32位),argument2在偏移sp+8,等等。由於這些調用約定是已知的,這些偏移硬編碼在你的代碼並且計算效率很高。

幀指針非常有用,因爲您也將局部變量推入堆棧,並且您不希望索引參數在不同位置更改,因此幀指針在整個過程的執行過程中提供了穩定的錨點。

3

不,不需要從堆棧中彈出參數來查看它們; @eli說,通常的做法是使用「幀指針」寄存器。實際上,68k甚至有一個指令(LINK),它被設計用來實現這一點:它是一個單指令,它可以:(a)保存前一幀指針,(b)將當前堆棧指針複製到幀指針,以及(c)遞減指定量的堆棧指針爲局部變量留出空間。

這是example of C code and the corresponding 68000 assembler