2016-02-22 47 views
0

我很新裝配和嘗試學習自己。爲外部呼叫選擇特定的寄存器

到目前爲止,我已經瞭解到,根據從調用者傳遞給被調用者的參數數量,如果只有少量參數傳遞,而不是推/彈操作,只有一些特定的寄存器是用過的。

  • 例如,將參數傳遞給一個交換功能void asm_swap(int *x, int *y)時,C編譯器使用寄存器RCXRDX寄存器傳遞變量的地址(在這種情況下,不需要返回值)。切換從_cdecl_fastcall沒有任何區別。

  • 對於另一功能int asm_fact(int x),也就是計算x的階乘,C編譯器使用RCX傳遞x的值,並且RAX返回所計算的階乘。再次,從_cdecl切換到_fastcall沒有任何區別。

連接到這個問題,我有兩個問題:

  1. 我可以推斷斷言的是,每當我編譯相同的代碼時,用戶將肯定用於發送和接收數據相同的寄存器?
  2. 有沒有辦法來選擇特定的寄存器作爲一種工具來傳遞變量(比如,對於功能asm_fact,我寧願使用RDX舉行x的值,而不是RCX

系統:視窗10(64),VS-2013

樣品的編號: 文件 「的main.c」

#include <stdlib.h> 
#include <stdio.h> 

extern void asm_swap(); 
extern signed long long int asm_fact(); 

typedef signed long long int sint64; 

sint64 fact_sint64(sint64 n) { 
    sint64 ret = (sint64)1; 
    if (n > (sint64)1) { 
     while (n > (sint64)1) { 
      ret *= n--; 
     } 
    } 
    return (ret); 
} 

void swap_sint64(sint64 *a, sint64 *b) { 
    sint64 t = *a; 
    *a = *b; 
    *b = t; 
} 

int main(void) { 
    sint64 x, y; 
    x = 8; 
    y = 3; 
    printf("(initial)  -> x = %lli  y = %lli\n\n", x, y); 
    swap_sint64(&x, &y); 
    printf("(swap in c) -> x = %lli  y = %lli\n\n", x, y); 
    asm_swap(&x, &y); 
    printf("(swap in asm) -> x = %lli  y = %lli\n\n", x, y); 
    y = fact_sint64(x); 
    printf("(fact in c) -> fact(%lli) = %lli\n\n", x, fact_sint64(x)); 
    y = asm_fact(x); 
    printf("(fact in asm) -> fact(%lli) = %lli\n\n", x, y); 
    getchar(); 
    return (0); 
} 

文件 「Assembly.asm64」

.data 

.code 
asm_swap proc 
    mov r8, [rcx] 
    mov r9, [rdx] 
    mov [rcx], r9 
    mov [rdx], r8 
    ret 
asm_swap endp 

asm_fact proc 
    mov rax, 1 
    cmp rcx, 1 
    jle [email protected] 
[email protected]: 
    imul rax, rcx 
    dec rcx 
    cmp rcx, 1 
    jg [email protected] 
[email protected]: 
    ret 
asm_fact endp 
end 
+1

1)是2)否。參見[msdn](https://msdn.microsoft.com/en-us/library/zthk2dkh。aspx) – Jester

+1

這是*調用約定*的一部分,它是由實現定義的ABI(*應用程序二進制接口*)的一部分。 – EOF

+0

@Jester:非常感謝。那正是我所期待的。 – ssd

回答

1

對於Windows有一個ABI指定

  1. 如何參數傳遞
  2. 哪些寄存器需要在一個呼叫中保存

Msdn:microsoft calling conventions

爲了作爲C函數調用,您應該遵守通過這些規則。

您必須保存非易失性寄存器(保存並恢復它們)