Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 多参数masm x64上的Printf_C++_Assembly_X86 64_Masm - Fatal编程技术网

C++ 多参数masm x64上的Printf

C++ 多参数masm x64上的Printf,c++,assembly,x86-64,masm,C++,Assembly,X86 64,Masm,我需要在asm(Windows上)中创建一个复制以下行为的函数: _int64 q(_int64 a, _int64 b, _int64 c, _int64 d, _int64 e) { _int64 sum = a + b + c + d + e; printf("a = %I64d b = %I64d c = %I64d d = %I64d e = %I64d sum = %I64d\n", a, b, c, d, e, sum); return sum;

我需要在asm(Windows上)中创建一个复制以下行为的函数:

_int64 q(_int64 a, _int64 b, _int64 c, _int64 d, _int64 e) {
     _int64 sum = a + b + c + d + e;
      printf("a = %I64d b = %I64d c = %I64d d = %I64d e = %I64d sum = %I64d\n", a, b, c, d, e, sum);
      return sum;
}
我知道我需要为printf分配阴影空间,还需要在堆栈中存储一些参数,因为只有前4个参数在寄存器中(rcx、rdx、r8和r9)

我的问题是字符串格式和堆栈管理。 到目前为止,我的代码如下所示:

.data   
string1 dq 'a = %I64d b = %I64d c = %I64d d = %I64d e = %I64d sum = %I64d', 10, 0       ; The printf format, "\n",'0'

.code
    public      q                               ;a in rcx, b in rdx, c in r8, d in r9, e in stack
    q:          push rbp
                mov rbp, rsp                    
                sub rsp, 32                     ;allocating shadow space for printf
                                                ;for calling printf, we need to have [string] in rcx, 
                                                ;a in rdx, b in r8, c in r9, d in stack1, e in stack2, and sum in stack3
                add rax, rcx                    ;first make the sum
                add rax, rdx                    
                add rax, r8
                add rax, r9
                mov rbx, [rbp + 8]              ;getting e from the stack
                add rax, rbx                    ;final add, in rax now is sum
                push rax                        ;changing parameters in registers (last 3 in stack)
                push rbx
                push r9
                mov r9, r8                      ;c in r9
                mov r8, rdx                     ;b in r8
                mov rdx, rcx                    ;a in rdx
                lea rcx, [string]               ;string in rcx
                call printf
                mov rsp, rbp                    ;back to previous pointer
                pop rbp                         ;release resources
                ret 0
    end
此时它没有编译,带有

错误A2084:常量值太大


我不知道是否需要更改格式或将其拆分为2,在这种情况下,我需要在堆栈中存储一些其他参数,然后我不确定如何继续…

如果该错误与字符串在同一行,请使用
db
而不是
dq
:您不需要
10,0
元素填充为qwords,即使它确实像NASM那样接受引用的部分作为字符串

我认为MASM允许为
db
引用常量,因此应该可以将其组装起来


然后我们在运行时会遇到多个其他错误:


此外,如果要在按下3个寄存器后恢复它们,则需要
sub rsp,32
在按下3个寄存器后保留阴影空间。否则,这24个字节是被调用函数(
printf
)看到的阴影空间的底部


但这是毫无意义的,因为你没有在通话后恢复它们。因此,您通过重击
rbx
,违反了调用约定;调用后,您似乎没有对它们做任何处理,因此只需使用call clobbered reg,或者最好首先计算正确的arg传递寄存器中的值。

如果该错误与字符串在同一行,请使用
db
而不是
dq
:您不需要
10,0
元素填充为qwords,即使它确实像NASM那样接受引用的部分作为字符串

我认为MASM允许为
db
引用常量,因此应该可以将其组装起来


然后我们在运行时会遇到多个其他错误:


此外,如果要在按下3个寄存器后恢复它们,则需要
sub rsp,32
在按下3个寄存器后保留阴影空间。否则,这24个字节是被调用函数(
printf
)看到的阴影空间的底部


但这是毫无意义的,因为你没有在通话后恢复它们。因此,您通过重击
rbx
,违反了调用约定;在调用之后,您似乎没有对它们做任何处理,因此只需使用call clobbered reg,或者最好首先计算正确的arg passing寄存器中的值。

哪一行是错误?在绳子上?使用
db
,您不希望
10,0
元素填充到qwords中,即使它确实像NASM那样接受qwords。此外,如果您想在之后恢复它们,您需要
sub rsp,32
以在按下3个寄存器后保留阴影空间。否则,这24个字节是被调用函数(
printf
)看到的阴影空间的底部。但这是毫无意义的,因为你没有在通话后恢复它们。因此,您通过重击
rbx
,违反了调用约定;使用不同的注册表。另外,您还需要
调用_printf
,因为Windows就是这样装饰C名称的。@PeterCordes在字符串声明中是。。。因此,我有以下错误A2006:未定义符号:string错误在哪一行?在绳子上?使用
db
,您不希望
10,0
元素填充到qwords中,即使它确实像NASM那样接受qwords。此外,如果您想在之后恢复它们,您需要
sub rsp,32
以在按下3个寄存器后保留阴影空间。否则,这24个字节是被调用函数(
printf
)看到的阴影空间的底部。但这是毫无意义的,因为你没有在通话后恢复它们。因此,您通过重击
rbx
,违反了调用约定;使用不同的注册表。另外,您还需要
调用_printf
,因为Windows就是这样装饰C名称的。@PeterCordes在字符串声明中是。。。因此,我有以下错误A2006:未定义符号:StringThank,现在它可以工作,但e和sum不能正常工作。我真的不理解最后一段,但是:S。我是否仍然需要为printf分配阴影空间才能使用它???@MartaLobo:是的,您调用的任何函数都可以在返回地址上方超过32字节。您需要确保这些字节中没有任何有价值的内容。现在它已经组装好了,使用一个调试器来找出在执行单个步骤时代码在做什么。但是我注意到你从添加rax,rcx开始,而不是从mov开始,rax最初保存你的调用者留下的垃圾。是的,我注意到了,我添加了几个异或来重置寄存器。现在我唯一剩下的问题是如何从堆栈中获取“e”并适当地添加它…@MartaLobo:你有没有试过只查看C函数的优化编译器输出?打开函数并用x86-64 MSVC
-Ox
编译它。不要忘记在堆栈args之前,您自己的调用方在返回地址上方留下的阴影空间。非常感谢,该网站非常有用!谢谢,现在它可以工作了,但是e和sum不能正常工作。我真的不理解最后一段,但是:S。我是否仍然需要为printf分配阴影空间才能使用它???@MartaLobo:是的,您调用的任何函数都可以在返回地址上方超过32字节。您需要确保这些字节中没有任何有价值的内容。现在它已经组装好了,使用一个调试器来找出在执行单个步骤时代码在做什么。但是我注意到你从添加rax,rcx开始,而不是从mov开始,rax最初保存你的调用者留下的垃圾。是的,我注意到了,我添加了几个异或来重置寄存器。现在我唯一的问题是