2016-02-22 17 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函数调用,您应该遵守通过这些规则。

您必须保存非易失性寄存器(保存并恢复它们)