Ваша строка формата не соответствует тому, что вы получаете invoke
для передачи.
Вы используете %d
преобразование для узких аргументов, которые вам не подходят повышение до int
. %hhd
и %hd
- это, соответственно, необходимые преобразования для int8_t
(целое число со знаком) и int16_t
(short
). ISO C не указывает, что short = int16_t, но это относится к 32-битным Windows.
В любом случае, старшие байты этих 4-байтовых слотов стека для передачи этих узких целых чисел могут содержит большое количество мусора, если MASM invoke
магически не подписывает или не расширяет их нулями.
Кроме того, short
обычно является 16-битным байтом, но вы используете dd
. Это не должно иметь значения в этом случае, так как 32-битный код всегда использует как минимум 32-битные слоты стека для передачи аргументов.
Для дальнейшей отладки самостоятельно: Посмотрите, как это вызывается директива или макрос на самом деле собирается в настоящие машинные инструкции. т.е. разобрать полученный код, чтобы увидеть, что он на самом деле делает. (Или используйте отладчик с видом разборки в один шаг). Также используйте отладчик для просмотра стековой памяти после каждого шага, перед call
, чтобы проверить, правильно ли передаются ваши аргументы.
Если вы не уверены, что правильно Последовательность необходимых вам asm-инструкций: посмотрите на вывод компилятора из C или C ++ компилятора, чтобы найти эквивалентный код, который вызывает sprintf с C глобальными переменными того же типа, что и вы. (Например, для https://godbolt.org/, в котором доступно 32-разрядное x86 MSV C. Его соглашение о вызовах и ширина типов должны соответствовать тем, которые crt_sprintf
ожидает, что вы связываете через MASM32.)
Кроме того, все поплавки разбиты, потому что вы забыли применить продвижение по умолчанию C для поплавка, чтобы удвоить , что всегда происходит для аргументов в части ...
переменной c функция. Как напечатать число с плавающей запятой одинарной точности с помощью printf Таким образом, ваши 4-байтовые числа пересекают все позже.
И, аналогично, у вас есть dq
64-битные целые числа, но вы все равно говоря sprintf они %d
(int). Таким образом, вы на самом деле получаете верхнюю и нижнюю половины dq
, считываемые двумя отдельными %d
преобразованиями, что приводит к неправильному преобразованию, читающему неправильные байты.
Я изменил все byte
, word
и dword
для подписанных типов, и это работало хорошо, но у меня проблемы с qword
и real4
. Я изменил %d
для %ld
для qword
, но он по-прежнему помещает 0 в следующую запись, сдвигая все числа после нее.
В 32-битных ABI long
по-прежнему 32-битный тип. Вам нужно long long
и преобразование для этого %lld
для dq
.
А насчет поплавков, как я понял из ссылки на другую ветку, которую вы разместили - невозможно распечатать поплавок, мне нужно как-то преобразовать его в другой тип?
Это правильно. Вы просто не можете использовать invoke
с real4
для функций, похожих на printf, которые получают свои аргументы через ...
часть функции C variadi c.
Посмотрите на компилятор сгенерированный код для эквивалентного C.
. Вам придется преобразовать ваши real4
в double
и pu sh их вручную, прежде чем вызывать. (Вызывает нажатия в порядке справа налево, последние аргументы нажимаются первыми, поэтому вы можете сделать эти нажатия и затем использовать invoke
Я полагаю?)
Также ваша библиотека c, вероятно, использует long double
= double
(см. Комментарии к этому ответу), а не 10-байтовый тип x87. Так что, вероятно, нет способа заставить этот sprintf обрабатывать тбайт, и вам придется также преобразовать его в double
. Или просто не потрудитесь использовать real10
, если вы не найдете библиотеку C, которая может с этим справиться.
(О, это вы задали этот вопрос. Это все та же проблема.)