带有多个参数的masm x64上的Printf

时间:2018-09-26 21:51:41

标签: c++ assembly x86-64 masm masm64

我需要在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,那样的话我需要在堆栈中存储其他参数,然后我不确定如何继续...

请,我将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:2)

如果该错误与字符串一起出现,请使用db而不是dq:即使将10, 0元素确实接受了引号,您也不想将db元素填充到qwords中就像NASM一样是字符串。

我认为MASM允许call _printf用引号引起来的常量,因此应该对其进行汇编。


但不是链接:您将需要sub rsp, 32,因为这是Windows装饰C名称的方式。

然后在运行时还有其他多个错误:

此外,如果要在之后恢复它们,则需要printf在之后保留影子空间 。否则,这24个字节是被调用函数(rbx)看到的阴影空间的底部。

但这没什么意义,因为您没有在通话后恢复它们。因此,您破坏Weight | visit | Fat | Married 101 1 0 0 201 0 1 0 760 0 0 1 会违反调用约定;调用后看起来好像没有对它们进行任何操作,因此只需使用调用密集的reg,或者最好首先计算正确的arg-passing寄存器中的值。