【发布时间】:2018-09-26 21:51:40
【问题描述】:
我需要在 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,您不希望将10, 0元素填充到qwords,即使它确实像NASM 那样接受了这一点。 -
另外,如果你想在之后恢复它们,你需要
sub rsp, 32在推送 3 个寄存器之后保留影子空间。否则,这 24 个字节是被调用函数 (printf) 看到的影子空间的底部。但这毫无意义,因为您不会在通话后恢复它们。因此,您通过破坏rbx违反了调用约定;使用不同的注册。此外,您还需要call _printf,因为这就是 Windows 装饰 C 名称的方式。 -
@PeterCordes 是在字符串声明中......我有以下错误 A2006: undefined symbol : string