在 masm x64 上打印具有多个参数

Printf on masm x64 with multiple parameters

本文关键字:参数 打印 masm x64      更新时间:2023-10-16

我需要在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 = %I64dn", 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保留影子空间。 否则,这24个字节是被调用函数(printf(看到的阴影空间的底部。

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