我需要在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,那样的话我需要在堆栈中存储其他参数,然后我不确定如何继续...
请,我将不胜感激。谢谢!
答案 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寄存器中的值。