Реализует ли WINE "_printf" и подобные функции в MSVCRT? - PullRequest
0 голосов
/ 21 июня 2019

Вот пример программы, которая иллюстрирует мою проблему, ее можно скомпилировать с помощью FlatAssembler без использования компоновщика:

format PE console
entry start

include 'win32a.inc'

section '.text' code executable
start:

mov dword [esp],_output1
call [printf]
mov dword [esp+4],first
mov dword [esp],_input
call [scanf]

mov dword [esp],_output2
call [printf]
mov dword [esp+4],second
mov dword [esp],_input
call [scanf]

finit
fld dword [first]
fabs
fld dword [second]
fxch
fld1
fxch
fyl2x
fldl2e
fdivp st1,st0
fmulp st1,st0
fldl2e
fmulp st1,st0
fld1
fscale
fxch
fld1
fxch
fprem
f2xm1
faddp st1,st0
fmulp st1,st0
fstp dword [result]

fld dword [result]
fst qword [esp+4]
mov dword [esp],_output
call [printf]
invoke system,_pause
invoke exit,0

_output1 db "Enter the first number: ",0
_output2 db "Enter the second number: ",0
_input db "%f",0
_pause db "PAUSE",0
_output db "The first number to the power of the second number is: %f.",10,0

section '.rdata' readable writable
result dd ?
first dd ?
second dd ?

section '.idata' data readable import
library msvcrt,'msvcrt.dll'
import msvcrt,printf,'printf',system,'system',exit,'exit',scanf,'scanf'

Итак, ожидаемый результат, конечно, примерно такой:

Enter the first number: -2.5
Enter the second number: -2
The first number to the power of the second number is: 0.16

И это действительно вывод, который я получаю, если запускаю эту программу в Windows 10. Однако, если я пытаюсь запустить эту программу в WINE в Oracle Linux, я получаю:

000f:fixme:service:scmdatabase_autostart_services Auto-start service L"MountMgr" failed to start: 2
000f:fixme:service:scmdatabase_autostart_services Auto-start service L"WineBus" failed to start: 2
wine: Bad EXE format for Z:\home\teo.samarzija\Documents\Assembly\debug.exe.

Есть идеи, что происходит?

Я провел небольшое исследование и не могу найти никаких ссылок, подтверждающих, что _printf и _scanf даже реализованы в MSVCRT WINE. Однако я не уверен, что это проблема, и, если это проблема, то это единственная проблема.

Ответы [ 2 ]

1 голос
/ 25 июня 2019

Однако, если я попытаюсь запустить эту программу в WINE на Oracle Linux, вывод, который я получаю:

000f:fixme:service:scmdatabase_autostart_services Auto-start service L"MountMgr" failed to start: 2
000f:fixme:service:scmdatabase_autostart_services Auto-start service L"WineBus" failed to start: 2
wine: Bad EXE format for Z:\home\teo.samarzija\Documents\Assembly\debug.exe.

Ошибка "Bad EXE format" - это нечто совершенно иное. Это не означает, что проблема заключается в отсутствующей импортированной функции. Загрузчик никогда не заходил так далеко. Он даже не смог прочитать ваш двоичный файл. Это очень вероятно вызвано несоответствием битности. Например, попытка запустить 64-разрядное приложение в 32-разрядной системе.

Помимо этой проблемы, стоит отметить, что попытка использования функций библиотеки времени выполнения C по своей природе непереносима. может работать, если Wine (или любая другая среда выполнения) предоставляет функцию с идентичной подписью, но, скорее всего, не будет.

Полагаю, мне следует уточнить, так как вызов "1012 * * стандартной функции библиотеки времени выполнения библиотеки" непереносимой "может вызвать недоумение. Эти функции переносимы на уровне исходный код , но не на уровне двоичный . Даже без дополнительной сложности Wine функции библиотеки времени выполнения C являются непереносимыми, поскольку CRT от Microsoft имеет версию - вы должны ссылаться на соответствующую версию и иметь эту DLL-библиотеку доступной во время выполнения или вашего приложения. не сработает.

Именно из-за этой проблемы Windows предоставляет оболочки для этих стандартных функций как часть API базовой платформы, которая доступна повсеместно. Если вы хотите быть полностью переносимым для всех реализаций среды Win32, и вы не ссылаетесь на свою собственную копию библиотеки времени выполнения C, вам следует вместо этого вызывать эти функции.

Версия sprintf для Win32: wsprintf. Он имеет тот же интерфейс, что и sprintf, так что вы можете назвать его так же, как замену. Фактически, хотя вы не должны полагаться на это, он реализован в Windows как простая оболочка для версии sprintf, предоставляемой локальной копией библиотек времени выполнения C.

Если вам нужна версия, в которую вы можете передать список аргументов (например, vsprintf), вы можете позвонить wvsprintf.

Обратите внимание, что в отличие от большинства функций Windows API, эти функции используют соглашение о вызовах __cdecl, а не соглашение о вызовах __stdcall. Убедитесь, что вы придерживаетесь этого в коде сборки. Короче говоря, это означает передачу аргументов справа налево и очистку стека на сайте вызовов.

Однако Microsoft отказалась от этих функций, поскольку они не совсем безопасны (возможны переполнения буфера и т. Д.). В качестве замены они предлагают функции в заголовке StrSafe.h. Эти функции бывают двух вариантов: те, которые принимают количество байтов (Cb) и те, которые принимают количество символов (Cch). Относящиеся к этому обсуждению будут либо StringCbPrintfA, либо StringCchPrintfA. Однако их сложнее использовать на ассемблере, потому что они предназначены для использования встроенным путем простого включения заголовочного файла StrSafe.h. Вы можете использовать их в виде библиотеки, но тогда вам нужно будет передать соответствующие заглушки StrSafe.lib компоновщику. Обратите внимание, что ссылка на эту библиотеку означает, что ваше приложение будет работать только в Windows XP с пакетом обновления 2 или более поздней версии.

Это приведет вас на полпути. Вы на самом деле пытаетесь позвонить printf, а не sprintf. Разрыв, конечно же, заключается в получении отформатированной строки, записанной в консоль. Если у вас есть отформатированная строка (сгенерированная wsprintf, StringCchPrintfA или любым другим), это можно сделать, вызвав функцию WriteConsole, которая является Win32 API для записи вывода в консоль. окно. Если вы хотите STDOUT, вам сначала нужно открыть этот дескриптор с помощью GetStdHandle(STD_OUTPUT_HANDLE).

0 голосов
/ 18 июля 2019

Во всяком случае, я получил ответ:

https://www.linuxquestions.org/questions/linux-general-1/can%27t-install-wine-on-64-bit-oracle-linux-4175655895/page2.html#post6012838

Короче говоря, для 64-битной Oracle Linux WINE необходимо скомпилировать из исходного кода для правильной работы.

...