Printf на masm x64 с несколькими параметрами

Мне нужно создать функцию в 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 ответ

Решение

Если эта ошибка находится в строке со строкой, используйте db вместо dq: ты не хочешь 10, 0 элементы дополняются до qwords, даже если он принимает цитируемую часть в виде строки, как это делает NASM.

Я думаю, что MASM допускает цитируемые константы для db, так что должен его собрать.


Но не ссылка: вам нужно call _printf потому что именно так Windows украшает имена C.

И затем у нас есть несколько других ошибок во время выполнения:

Кроме того, вам нужно sub rsp, 32зарезервировать теневое пространство после нажатия 3 регистров, если вы хотите восстановить их после. В противном случае эти 24 байта являются нижней частью теневого пространства вызываемой функции (printf) видит.

Но это бессмысленно, потому что вы не восстанавливаете их после звонка. Таким образом, вы нарушаете соглашение о вызовах, забивая rbx; Не похоже, что вы что-то делаете с ними после вызова, поэтому просто используйте reg-clobbered reg или лучше сначала вычислите значение в правом регистре передачи аргументов.

Другие вопросы по тегам