c++ - 具有多个参数的 masm x64 上的 Printf

标签 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;
}

我知道我需要为 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

此时它不编译,有一个

error A2084: constant value too large

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

最佳答案

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

我认为 MASM 允许为 db 引用常量,因此应该可以进行汇编。


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

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

但这毫无意义,因为您没有在通话后恢复它们。所以你通过破坏 rbx 违反了调用约定;看起来你在调用之后没有对它们做任何事情,所以只需使用调用破坏的 reg,或者更好地首先计算正确的 arg 传递寄存器中的值。

关于c++ - 具有多个参数的 masm x64 上的 Printf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52526488/

相关文章:

c++ - 如何通过引用传递从 stringstream 检索到的字符串?

c++ - 在位流中扫描位模式的最快方法

c - 从 C 编译器理解 MIPS 汇编代码

c++ - 为什么使用 leal 而不是 incq?

c++ - 强制 C++ 函数的用户承认作为数值常量的参数的语义含义的最佳方法是什么?

c++ - 将 char 与 int 连接起来

c++ - 在 C++ Core Guidelines Per.4 中,为什么坏示例旨在更快?

c - ARM 上的高效复制,两个 16 位提取还是 1 个 32 位?

c# - return 可以抛出异常吗?

c - 如何以编程方式禁用不可屏蔽中断?