Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Получение "чистого" кроссплатформенного


Автор: Rickert 11.1.2008, 17:38
Допустим я составляю программу:
Код

#include <stdio.h>
int main(int argc, char** argv)
{
  fprintf(stdout, "Hi\n");
  return 0;
}

Допустим теперь скомпилируем его на VS 2005. Ясно понятно, что получится PE файл, но вот вопрос: если я теперь отброшу PE заголовок, то получилу ли чистый кроссплатформенный код, который может быть выполнен под любой ОС?
Скорее всего тут будет играть роль версия компиляции: debug || release?

Автор: nickless 11.1.2008, 17:52
Цитата(Rickert @  11.1.2008,  15:38 Найти цитируемый пост)
если я теперь отброшу PE заголовок, то получилу ли чистый кроссплатформенный код, который может быть выполнен под любой ОС?

Нет, тот же fprintf использует API той оси, под которую скомпилирована программа. Кроме того не всё зависит от оси, бывают еще и разные архитектуры процессоров smile 

Автор: Rickert 11.1.2008, 17:54
Разные архитектуры процессоров не в счёт. Возьмём за аксиому.
Хорошо, а разве тажа fprintf никак не  ретранслируется в машинный код? Она именно использует системные либы?

Автор: bsa 11.1.2008, 18:15
Rickert, fprintf входит в стандартную библиотеку Си. Т.е. если этот вызов не был соптимизирован компилятором (gcc иногда на fputs заменяет), то твоя прога будет ссылаться на эту библиотечную функцию.
Посмотри реализацию wine, думаю поймешь, почему нельзя.

Автор: Rickert 11.1.2008, 19:40
Хорошо, а если тело функции main будет состоять из asm кода и не будет использовать библиотек?

Автор: Mayk 11.1.2008, 20:04
Rickert, ты пытаешься решить какую то проблему, или ещё не прекратил отмечать новый год?


Автор: archimed7592 11.1.2008, 21:44
Цитата(Rickert @  11.1.2008,  17:54 Найти цитируемый пост)
Хорошо, а разве тажа fprintf никак не  ретранслируется в машинный код?

А как её можно ретранслировать в машинный код? В одном случае это будет запись в "экранный" буфер, во втором - отрисовка пикселей(в гр. режиме), в третьем запись в файл, причём, ФС может быть произвольной, устройство хранения может быть произвольным и т.д. В четвёртом случае, к примеру под *nix файлом может быть что угодно - от мышки, до сетевой платы.

Автор: Rickert 11.1.2008, 21:48
Цитата(Mayk @  11.1.2008,  20:04 Найти цитируемый пост)
Rickert, ты пытаешься решить какую то проблему, или ещё не прекратил отмечать новый год?

Да, есть задача: написать клиент - сервер приложение. Сервер посылает пакет, который представляет собой машинные коды на выполнение, а клиент должен их принять и выполнить.
Встал вопрос кроссплатформенности.
archimed7592, я прекрасно понимаю твою мысль, но всё - таки: если писать на чистом ассемблере, ведь есть прерывания и номера функций, которые везде едины, ведь, процесор - то всё равно знает ограничнный набор команд, которые он и получает в независимости от ОС?

Автор: jonie 11.1.2008, 22:47
используйте для этих целей другой язык __не__ транслирующий свою работу в бинарник. Например perl\lua\c#\java\php.. ну я думаю мысль понятна)

Автор: Mayk 11.1.2008, 22:57
... или даже си/си++  
но в этом случае передавать надо не машинные коды, а исходник, чтобы клиенты его компилировали.

Автор: vadiml 11.1.2008, 23:25
мне придумался только 1 случай, когда не надо перекомпилировать код при переносе с машины на машину с разными OS -- использование интерпретатора

в наиболее используемых интерпретаторах есть все сетевые библиотеки.

я, например, клиентские части, если они не требуют высокой скорости, пишу на перле, ранее на perl/Tk, сейчас на perl/Qt

а универсальных С вызовов нет, например strlen в линуксе фактически вызывается из glibc. Можно даже не искать исходники, а просто посмотреть backtrace на разных системах для любых функций.

Автор: archimed7592 12.1.2008, 10:35
Цитата(Rickert @  11.1.2008,  21:48 Найти цитируемый пост)
едь есть прерывания и номера функций, которые везде едины,

Пример таких, везде единых прерывания/портов можно?

Автор: bsa 12.1.2008, 11:53
Цитата(Rickert @ 11.1.2008,  21:48)
если писать на чистом ассемблере, ведь есть прерывания и номера функций, которые везде едины, ведь, процесор - то всё равно знает ограничнный набор команд, которые он и получает в независимости от ОС?

В защищенном режиме все программные прерывания вызывают исключения, которые обрабатываются монитором защищенного режима (читай, ядром). Именно через них делаются так называемые "системные вызовы" - обращение программы к ядру системы. Такие обращения происходят при малейшем чихе программы, например, выделение памяти, открытие/закрытие файлов/сокетов и пр. Причем, у каждой ОС системные вызовы разные (я уж не говорю о том, что номера могут отличаться). Аппаратные прерывания и порты вообще прикладной программе недоступны, любое обращение к аппаратному порту приведет к исключению и убиванию программы ядром.
Конечно, ты можешь написать на ассемблере код, который не обращается к ядру и все внутренние вызовы у него сделаны относительными (правда, нет у меня уверенности, что ОС позволит его выполнить, но это уже другой вопрос). Вот только какой смысл это делать? Разве "математику" (а это именно математика, так как все остальное системозависимо) нужно передавать в машинных кодах на другой комп? Если тебе так неймется, то либо воспользуйся готовыми скриптовыми языками (lua, perl, python и т.п.), либо создай свой узкозаточенный.

Автор: Rickert 12.1.2008, 13:33
Всем спасибо! smile 

Автор: MAKCim 12.1.2008, 16:02
Цитата(archimed7592 @  11.1.2008,  21:44 Найти цитируемый пост)
А как её можно ретранслировать в машинный код?

fprintf - это функция libc
через readelf находим ee смещение в libc*.so* и размер
бинарные данные, находящиеся там, и есть машинный код
если повезет, он будет даже позиционно-независимым 
Цитата(bsa @  12.1.2008,  11:53 Найти цитируемый пост)
Аппаратные прерывания и порты вообще прикладной программе недоступны, любое обращение к аппаратному порту приведет к исключению и убиванию программы ядром.

в общем случае не доступны
в частном же через iopl() можно получить доступ к in/out инструкциям
естественно, для этого процесс должен иметь CAP_SYS_RAWIO capability

Автор: archimed7592 13.1.2008, 06:59
Цитата(MAKCim @  12.1.2008,  16:02 Найти цитируемый пост)
fprintf - это функция libc
через readelf находим ee смещение в libc*.so* и размер
бинарные данные, находящиеся там, и есть машинный код
если повезет, он будет даже позиционно-независимым 

Макс, ты же и сам отлично понимаешь, что это не кроссплатформенно даже в примитвном случае win/lin. Что уж говорить о более "изощрённых " вариантах? smile 

Автор: MAKCim 13.1.2008, 10:31
Цитата(archimed7592 @  13.1.2008,  06:59 Найти цитируемый пост)
Макс, ты же и сам отлично понимаешь, что это не кроссплатформенно даже в примитвном случае win/lin. Что уж говорить о более "изощрённых " вариантах?

вопрос был в том, как получить машинный код
Цитата(archimed7592 @  11.1.2008,  21:44 Найти цитируемый пост)
А как её можно ретранслировать в машинный код?

 smile 
а что касается кроссплатформенности (в рамках адной архитектуры), то ее можно достичь только если машинный код не использует средств обращения к ОС (или к функциям библиотек конкретных ОС) (типа INT, SYSENTER, SYSCALL, FAR CALL), т. е, допустим, реализует какой-либо алгоритм вычисления чего-либо 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)