Перейти к контенту
Азраэль

Курилка программистов

Рекомендуемые сообщения

5 минут назад, НаноБот сказал:

@abramcumner Оператор ORG в асме, это задать адрес кода, без него всё это невозможно.

Я знаю, что такое ORG, и еще раз повторю ORG в асме, в с++ extern.

 

И плюс, у компилятора куча ограничений, не не получится, С/С++ невозможно использовать в  XRayExtensions  проекте.

Нет у компилятора никаких ограничений, с++ может генерировать точно такие же объектники, как и асм. Ну и я как бы делал хрей-экст на с++ :)


Подарки

  • Ссылка на комментарий
    1 час назад, abramcumner сказал:

    extern

    Это внешняя функция, ну а как задать собственно адрес задать?

    org 10227DAAh - shift

    А как такая строчка в С++ будет выглядить?

    ...в конце концов, важен лишь, машинный код.

    СТАЛКЕР только для ПК!

    Ссылка на комментарий
    20 минут назад, НаноБот сказал:

    А как такая строчка в С++ будет выглядить?

    Эта строчка так и останется в xrgame_stubs.asm.

     

    org 105602E8h - shift
    g_Actor dword ?
    
    

    В с++ напишешь:

    
    extern CActor* g_Actor;
    
    

    И можешь обращаться к g_Actor из c++.


    Подарки

  • Ссылка на комментарий
    В 01.04.2018 в 04:57, Malandrinus сказал:

    Это как? Может у тебя версия старая?

    Новая, старая, какая разница, МАСМ глючный, забагованный ассемблер. Но есть альтернатива, например UASM, МАСМ совместимый ассемблер с расширенными возможностями. Есть ещё asmC, так же форк JWasm, как и UASM. Правда в этих ассемблерах нет оператора для вычисления выражения, но это можно подправить. Исходники UASM и asmC выложены на ГитХабе.

    ЗЫ

    Интересно эти ассемблеры не являются на все 100% совместимыми с МАСМ, так как у них более высокие требования к ошибкам, но если эти ошибки устранить, то всё заработает.

    ЗЫЫ

    И ещё UASM быстрей компилирует, гораздо быстрей, проект XRayExt для ТЧ всего за 0.6 сек, что по сравнению с МАСМом быстрей в 28 раз!

    Изменено пользователем НаноБот

    ...в конце концов, важен лишь, машинный код.

    СТАЛКЕР только для ПК!

    Ссылка на комментарий
    On 5/21/2018 at 7:43 PM, НаноБот said:

    МАСМ глючный, забагованный

     

    Не замечал за MASM особенных багов. Максимум, что мне от него было надо - компилировать код, генерируемый IDA. С этим MASM вполне справлялся. Единственная проблема была с версией 6 из состава Masm32. Но там был не баг, а просто старая версия, которая не поддерживала новые инструкции процессора. С трудом себе могу представить, что такое надо написать, чтобы ассемблер начал глючить. Если же речь идёт о глюках в препроцессоре, то это в ассемблере вообще от лукавого.

     

    On 5/21/2018 at 7:43 PM, НаноБот said:

    UASM быстрей компилирует, гораздо быстрей, проект XRayExt для ТЧ всего за 0.6 сек,

     

    Можно подумать, у тебя проект с компиляцией в пару часов.

     

    Не напомнишь, какая вообще мотивация продолжать использовать ассемблер?

     

    Плагины Total Commander для работы с игровыми архивами:

    Архиваторный плагин (для работы с одиночным архивом): link1 link2

    Системный плагин (для распаковки установленной игры): link1 link2

     

    Ссылка на комментарий
    В 25.05.2018 в 00:28, Malandrinus сказал:

    Не замечал за MASM особенных багов.

    Если кодить на чистом ассемблере, то проблем особо нет. Но я активно использую макрокоманды .if, .while, proc и тд. а вот они то, и не работают как надо. Например:

    .if (esi && g_alive(esi))

    ...

    .endif

    Компилируется с ошибками, сначала идёт макрос g_alive. а затем проверка esi. В общем, мне не нужен С/С++, а нужен ассемблер высокого уровня с операторами высокого уровня, как в С/С++, с поддержкой ООП, типов, оператор выражения и так далее. Короче, UASM это частично решает, поэтому придётся его допиливать самому, потом может с разработчиками свяжусь чтобы мой код со своим слили.

     

    Новость!

    https://news.microsoft.com/2018/06/04/microsoft-to-acquire-github-for-7-5-billion/

    Мелкософт купил GitHub! Вопрос? Чем нам это грозит?

    Изменено пользователем НаноБот

    ...в конце концов, важен лишь, машинный код.

    СТАЛКЕР только для ПК!

    Ссылка на комментарий
    10 hours ago, НаноБот said:

    сначала идёт макрос g_alive. а затем проверка esi.

    Вот здесь я не понял. А как ты хотел, чтобы макрос препроцессора выполнялся на этапе выполнения программы?

     

    В целом то, что ты делаешь, - это путь в никуда. Ассемблер существует с единственной целью - чтобы компилировалось ровно то, что написано. Это важно, это изначальная суть ассемблера - последовательность инструкций процессора. Ты смотришь на код и точно знаешь, что получишь в итоге.

     

    У тебя же идёт уход в прямо противоположную сторону - нагромождение макросов препроцессора  и даже кодогенерирующих директив (типа того же .IF). Какой в этом смысл? Такими вещами гораздо удобнее заниматься в языках высокого уровня, а ассемблер оставить для сугубо ограниченных целей: критические по производительности моменты и непосредственный доступ к железу в драйверах.

     

    Были бы у меня исходники изначально - не потратил бы ни секунды на всю эту возню с ассемблером. Более непроизводительного, неудобного и глючного способа писать код я в жизни не видал. Впрочем, у меня тогда не было другого выхода. Я отчётливо помню тот момент, когда решил влезть во всю эту историю с ассемблером. Я тогда для гравипушки придумал крайне извращённый способ отловить нажатие клавиши огня - по отлову быстрого расхода патронов. После этого я и понял, что это - предел и дальше чистыми скриптами ничего не развить. И тут как раз связался с Колмогор-ом насчёт этого его способа делать правки. Оттуда и завертелось. Но вот мотивации заниматься этим сейчас я не понимаю. Впрочем, каждому своё.

     

    10 hours ago, НаноБот said:

    Чем нам это грозит?

    В ближайшей перспективе ничем. Вроде пока ничего не собираются менять. А даже если и закроют - полно других свободных хостингов.

     

    Плагины Total Commander для работы с игровыми архивами:

    Архиваторный плагин (для работы с одиночным архивом): link1 link2

    Системный плагин (для распаковки установленной игры): link1 link2

     

    Ссылка на комментарий

    Мне не нравится С++, особенно С++11 и более новые редакции, я просто не умею этой новой всей фигнёй пользоваться.

    Вот пример.

    Скрытый текст
    
    #include <iostream>
    #include <map>
    #include <stack>
    #include <functional>
    #include <utility>
    #include <stdlib.h>
    
    using namespace std;
    
    int main(int argc, char** argv)
    {
    	stack<double>				s;
    	stack< pair<int, char> >	ops;
    
    	auto p = [&s, &ops] (function<double (double, double)>& f) {
    		double r=s.top();
    		s.pop();
    		r=f(s.top(),r);
    		s.pop();
    		s.push(r);
    		ops.pop();
    	};
    
    	map< char, pair< int, function<double (double, double)> > > m ={
    		{'+', {1, [](double a, double b){return a+b;}}},
    		{'-', {1, [](double a, double b){return a-b;}}},
    		{'*', {2, [](double a, double b){return a*b;}}},
    		{'/', {2, [](double a, double b){return a/b;}}}
    	};
    
    	const	int	order = 2;
    			int	level = 0;
    	for (char* sp = argv[1];; ++sp) {
    		while (*sp == '(') {
    			level += order;
    			++sp;
    		}
    		s.push(strtod(sp, &sp));
    		while (*sp == ')') {
    			level -= order;
    			++sp;
    		}
    
    		if (!*sp) {
    			while(!ops.empty())
    				p(m[ops.top().second].second);
    			break;
    		}
    
    		const int op =  m[*sp].first + level;
    		while (!ops.empty() && ops.top().first >= op)
    			p(m[ops.top().second].second);
    
    		ops.push(make_pair(op, *sp));
    	}
    
    	cout << s.top() << endl;
    	return 0;
    }

     

    Я просто не понимаю это нагромождения заумного кода, ЧЁ, код читабельный, код оптимальный, да ладно. За годы ковыряния IDA Pro XRay-я, я изучил как компилирует С++, и какой код эффективный, а эффективный именно простой код, так же такой заумный код трудно отлаживается, если есть ошибка, то найти её не просто. Короче, С++ в последних редакциях просто чудовище, VS2017 весит аж 36 ГигаБайт, это уже не гипербола, это реальное чудовище. Давно заметил что программисты на С++ используют сложные методы, там, где можно обойтись более простыми методами. Ну типа колёса в технике определяют как vector или даже как map, хотя по факту это совсем не к чему, можно обойтись обычным динамическим массивом.

    Так что ассемблер высокого уровня рулит, писать на чистом ассме не слишком эффективно, особенно если надо потом портировать код в С/С++. Тут и выручает ассемблер типа UASM, исходники в наличии, так что под свои нужды доработать напильником не проблема.

    ЗЫ

    А g_alive это имитация инлайн метода С++, жив ли объект. В С++ выглядит так.

    if (npc && npc.g_alive() )

    ...

    Но на МАСМе это не работает, а вот на UASM работает, даже если g_alive просто функция.

    Так что UASM форева!

    ...в конце концов, важен лишь, машинный код.

    СТАЛКЕР только для ПК!

    Ссылка на комментарий

    Ну, это явно кто-то извращался. Именно с целью добиться максимальной нечитаемости. Но на масме видали извращения и хуже. Например, самомодификацию кода по ходу выполнения.

     

    А вот оптимизация -  чтобы ее сделать для современного процессора, нам просто ни кто не скажет, как.

    Через сколько команд можно повторно обращаться к тому же регистру на i3 ? А на ip5 ?

    Каково максимальное смещение для j* и одинаково ли оно для всех ?

    После какой команды это j* можно делать, а после какой - лучше вставить лишний nop ?

     

    P.S. И что, синтаксис обычного, не приплющенного c студия уже не позволяет ? Если так, пора уже, однако, делать нормальный мейкфайл для gcc, и переползать под него.

    Ссылка на комментарий

    Кстати, я ещё AddCode* написал именно на МАСМ, т.к. посчитал что так будет быстрей, естественно использовал HLL(команды высокого уровня). Когда портировал код на С, то пришлось помучится из-за неявных преобразований, при этом проект собирается только VS C++, на Pelles C собирать не хочет**. Так что ассме кодить надо, хотя бы потому, что, на нем быстрей выходит чем на С/С++. Вот такой парадокс.:az1000106:

    * - утилита для добавления своего кода в целевой файл. Поддерживает изменения адресов релокаций, добавляет секцию данных. Может генерировать файл addr.inc. В дальнейшим возможно будет добавлены другие возможности.

    ** - так что развивать утилиту на С/С++ не вижу смысла.

    Так что проекты на макроассемблере высокого уровня могут конкурировать с С/С++.

    ...в конце концов, важен лишь, машинный код.

    СТАЛКЕР только для ПК!

    Ссылка на комментарий

    Да как бы я и текстовые редакторы на micro-11 писал, было дело, с поддержкой мультиязычности и G-кода...

    Не считая всякого дискового и сетевого.

    (micro-11 - это упрощенная версия MACRO-11, для LSI/PDP и наших к1801).

     

    Но, в какой-то момент становится утомительно, а для современных, повторюсь, руками нормальную оптимизацию не сделать. Ну и библиотеки наработаны в основном для сей.

    Ссылка на комментарий
    16 минут назад, НаноБот сказал:

    Так что ассме кодить надо, хотя бы потому, что, на нем быстрей выходит чем на С/С++. Вот такой парадокс.

    Тут всё зависит от потребностей: хотите программы, которые будут эргономичные и выполнять только то, что вы напишете - кодьте на асме, хотите программы, которые будут читабельные и понятные всем - используйте другой язык. А парадокса, смелюсь предположить, никакого нет, т.к, когда вы пишите на асме, вы получаете, только то, что написали, когда вы пишете на, к примеру, cpp компилятор может заменить некоторые выражения на более простые\сложные. Правда, самому увидеть не приходилось - знаю сам факт. 

    Ссылка на комментарий

    @buffy, Кодить низкоуровнено и понятно, можно и на С++, просто не используйте всякий хлам вроде std, вот так, как показано в этом коде.

    Сейчас я пытаюсь от компилировать код сверху, сначала пытался VS2010, не получилось, т.к. это С+11, 2010 слишком стар, сейчас пытаюсь VS2017, конечно не без проблем, студия тут же запросила обновление Microsoft.Windows.81SDK (181 МБ), т.е. ей мало несколько гигабайт, кажется 3 скачал. Спрашивается на кой оно надо, это просто чудовище, мрак полный, а всё индусы, которым платят за объём кода, точней политика оплаты рукой-водителей мракософта. Мракософт корпорация зла.

    ЗЫ

    ХАХХАХА код всё равно не компилируется, #include <stdlib.h> не может открыть файл.

    Мда уж. Кстати, этот код с хабра, консольное приложение. Источник.

    https://habr.com/post/216449/

    ЗЫЫ

    А понял, надо установить платформу х64.

    ЗЫЫЫ

    Файл создан, но весит 59 кб, на асме такой же код, весил бы 2-3 кб максимум. И создать его бы не было проблемы. Почти столько же по времени.

    ЗЫЫЫЫ

    Не, однозначно, деградируют программисты, деградирует общество.

     

    Изменено пользователем НаноБот
    • Не нравится 1
    • Согласен 1
    • Полезно 1
    • Смешно 1

    ...в конце концов, важен лишь, машинный код.

    СТАЛКЕР только для ПК!

    Ссылка на комментарий

    @НаноБот, ёшкин кот;) вы наверное понимаете то, что ни один нормальный программист не будет писать на асме только для того, чтобы вывести надпись "Hello World"?)

    Ссылка на комментарий

    Вот для отправить в ./dev/stdout "Hello World !" или  типа того - асм не лишен смысла.

    Хотя сейчас есть awk, да и тот же LUA. В человеческих системах. Для инопланетян там же есть perl.

    • Смешно 1
    Ссылка на комментарий

    НаноБот,

    Quote

    Мне не нравится С++, особенно С++11 и более новые редакции, =)

    "Вы просто не умеете их готовить" (C)

    Quote

    g_alive это имитация инлайн метода С+

    Препроцессор (а ты говоришь о макросе препроцессора) - это средство времени ДО компиляции. Он берёт твой текст и преобразует его в другой текст, который затем уже и компилируется. Препроцессор по определению не делает ничего другого. Поэтому твоё пожелание, чтобы g_alive работал во время исполнения - заведомо некорректное. Этот макрос развернётся в что-то другое до того, как код вообще будет скомпилирован и уж всяко до исполнения. Инлайн-функции же работают совсем иначе. Инлайн функции - это конструкции времени компиляции, они учитывают контекст (своё окружение) а также все правила вызова функций.

     

    Когда ты имеешь дело с препроцессором, первый вопрос - хорошо ли ты понимаешь, что конкретно он делает. Без этого его использование чревато последствиями, поскольку ты видишь у себя один код, а реально компилируется что-то другое. Судя по всему, ты не до конца его понимаешь. Это нормально, препроцессор штука мутная, в случае с ассемблерами вообще не сильно стандартизированная и весьма специфичная для каждой конкретной версии и производителя, и именно поэтому его принято избегать.

     

    Quote

    всякий хлам вроде std

    :facepalm:

     

    Quote

    на асме такой же код, весил бы 2-3 кб максимум. И создать его бы не было проблемы. Почти столько же по времени.

    Я бы посмотрел, как ты написал бы на ассемблере парсер формул в 40 строк за пару часов (хотя наверняка этот код занял даже меньше).

     

    Dennis_Chikin,

    Quote

    Ну, это явно кто-то извращался. Именно с целью добиться максимальной нечитаемости

     

    Да нормальный код же! Ничего нечитаемого. И насчёт С++11 там ничего такого запредельного нет. Вполне можно было бы обойтись обычными указателями на функции, но и всё. К собственно читаемости алгоритма это никакого отношения не имеет.
     

    Quote

    А вот оптимизация -  чтобы ее сделать для современного процессора, нам просто ни кто не скажет, как

     

    Есть полная официальная документация на каждый процессор, в том числе и насчёт оптимизации. Другое дело, что это весьма пухлый документ для профильных специалистов, собственно создателей компиляторов и библиотек низкого уровня. Их же для того и пишут, чтобы каждому прикладнику не нужно было вникать во все эти детали. Для вас стараются, а вы нос воротите =)

     

    Ну и не надо забывать про разные платформы. Код на ассемблере будет работать на конкретной платформе. Код на языке высокого уровня будет работать везде, где есть соответствующий компилятор/интерпретатор.

     

    Quote

    синтаксис обычного, не приплющенного c студия уже не позволяет ?

    Всё позволяет. Вообще, Мелкософт много в чём можно упрекнуть, но их С/С++ компиляторы - одни из лучших и с каждой версией становятся только лучше.

     

    Плагины Total Commander для работы с игровыми архивами:

    Архиваторный плагин (для работы с одиночным архивом): link1 link2

    Системный плагин (для распаковки установленной игры): link1 link2

     

    Ссылка на комментарий
    4 минуты назад, Malandrinus сказал:

    и с каждой версией становятся только лучше.

    Ну я бы так не сказал.

    с 15.5 до 15.6.5(а это в районе года) компилятор был сломан: выдавал ICE на float a = powf(s, 128);

    c 15.7 до 15.7.2 снова был сломан(в районе месяца): что-то с шаблонами.

    Каждая минорная версия что-нибудь ломает :)


    Подарки

  • Ссылка на комментарий
    1 час назад, Malandrinus сказал:

    Я бы посмотрел, как ты написал бы на ассемблере парсер формул

    Но всё же неприятно, что программа, которая выводит какую-то надпись, весит 60кб.:dry:

    Изменено пользователем buffy
    Ссылка на комментарий

    @Malandrinus, РЕДАКТОР с поддержкой формул был написан. А также поддержкой сетевой работы, станков с ЧПУ, и со сжатием. В одном флаконе. Правда, в три руки, и за пару лет. С другой стороны, писалось студиозусами, в свободное от зарабатывания на кусок хлеба с икрой время. ;)

    1801вм1, 4 кило памяти, 512x256 8 цветов видео. Отдельно существовала читалка для готовых текстов. Полтора кило размером, функция сборки текста из нескольких кусков.

    Ссылка на комментарий

    Вот код на ассемблере UASM

    Скрытый текст
    
    ;=========================================================================
    ; Консольное утилита для вычисления выражений
    ; Для UASM 2.46.10.0
    ; Создан:				 9.06.2018 г. 20:30
    ; Изменения:			10.06.2018 г. 20:00
    ; (c) NanoBot
    ;=========================================================================	
    __MINIMAL_SIZE__		equ <>		; оптимизация на минимальный размер!
    
    .686
    .XMM
    
    .model flat, stdcall
    option casemap:none
    include f:\masm32\include\windows.inc
    include f:\masm32\include\user32.inc
    include f:\masm32\include\kernel32.inc
    include f:\masm32\include\masm32.inc
    include f:\masm32\include\msvcrt.inc
    include f:\masm32\macros\macros.asm
    includelib f:\masm32\lib\user32.lib
    includelib f:\masm32\lib\kernel32.lib
    includelib f:\masm32\lib\masm32.lib
    includelib f:\masm32\lib\msvcrt.lib
    
    
    __getmainargs		PROTO C :ptr, :ptr, :ptr, :dword, :ptr
    GetStartupInfoA		PROTO stdcall :ptr STARTUPINFOA
    main				PROTO C	argc:dword, argv:ptr, environ:ptr
    
    ;========================= MACROSES =========================
    LABEL_EXPR			equ 1b							; метка кода
    MEM_EXPR			equ 10b							; память
    IMM_EXPR			equ 100b						; непосредственное выражение
    DIRECT_ADDR			equ 1000b						; прямая адресация памяти
    REG_EXPR			equ 10000b						; регистр
    VALID_REF			equ 100000b						; валидное выражение
    MEM_SS_EXPR			equ 1000000b					; память относительно SS регистра
    EXTER_LABEL_EXPR	equ 10000000b					; внешняя метка
    VIMM_EXPR			equ (VALID_REF OR IMM_EXPR)		; 
    align_proc MACRO
    IFDEF __MINIMAL_SIZE__
    	align 1
    ELSE
    	align 16
    ENDIF
    ENDM
    align_data MACRO
    IFDEF __MINIMAL_SIZE__
    	align 1
    ELSE
    	align 4
    ENDIF
    ENDM
    
    @MEMSET MACRO Buf:req, value:req, count:req
    	LOCAL pBuf
    	push	edi
    	IF @InStr(1, <&Buf>, <&>) EQ 1
    		pBuf equ @SubStr(<&Buf>, 2)
    		IF ((OPATTR pBuf) AND DIRECT_ADDR) OR ((OPATTR pBuf) AND LABEL_EXPR)
    			mov	edi, offset pBuf
    		ELSE
    			lea	edi, pBuf
    		ENDIF
    	ELSEIFDIFI <Buf>, <edi>
    		mov	edi, Buf
    	ENDIF
    	IF value EQ 0
    	xor		eax, eax
    	ELSEIFDIFI <value>,<eax>
    	mov		eax, value
    	ENDIF
    	mov		ecx, (count+3)/4	; count - bytes
    	rep stosd
    	pop		edi
    	EXITM <>
    ENDM
    
    CVIRTUAL MACRO name_method:REQ, langType:REQ, retType:REQ, protoDef:VARARG
    	LOCAL sz1, sz2
    	pDef CATSTR <TYPEDEF PROTO >,<&langType&>,< (&retType&)>
    	IFNB <protoDef>
    		pDef CATSTR pDef, <, >, <&protoDef>
    	ENDIF
    	IFDEF curClass
    	sz2 CATSTR <_>, curClass, <_&name_method>	;; _curClass_method
    	ELSE
    	sz2 CATSTR <_>, <_&name_method>
    	ENDIF
    	% &sz2 &pDef
    ;;	% echo &sz2 &pDef
    	% sz1 typedef PTR &sz2
    	% name_method sz1 ?
    ENDM
    ;=============================================================
    
    char					typedef byte
    ;double					typedef real8
    true					equ 1
    false					equ 0
    MAX_STACK				equ 128
    
    stOperation struct	; (sizeof = 8 bytes)
    	CVIRTUAL	func, <FASTCALL>, <VOIDARG>, a:ptr real8, b:ptr real8
    	priority	sdword ?
    stOperation ends
    .data
    ;----------------------------------------------------------------------------
    .code
    ; СТАРТОВЫЙ КОД
    mainCRTStartup proc C
    local argc:dword, argv:LPVOID, environ:LPVOID, _si:STARTUPINFOA
    	mov		_si.cb, sizeof STARTUPINFOA
    	invoke	GetStartupInfoA, addr _si
    	invoke	__getmainargs, addr argc, addr argv, addr environ, 0, addr _si
    	invoke	main, argc, argv, environ
    	invoke	ExitProcess, eax
    mainCRTStartup endp
    ;----------------------------------------------------------------------------
    align_proc
    _add proc FASTCALL (VOIDARG) a:ptr real8, b:ptr real8
    ; a equ ecx, b equ edx
    	fld		real8 ptr [a]
    	fadd	real8 ptr [b]
    	fstp	real8 ptr [a]
    	ret
    _add endp
    
    align_proc
    _sub proc FASTCALL (VOIDARG) a:ptr real8, b:ptr real8
    	fld		real8 ptr [a]
    	fsub	real8 ptr [b]
    	fstp	real8 ptr [a]
    	ret
    _sub endp
    
    align_proc
    _mul proc FASTCALL (VOIDARG) a:ptr real8, b:ptr real8
    	fld		real8 ptr [a]
    	fmul	real8 ptr [b]
    	fstp	real8 ptr [a]
    	ret
    _mul endp
    
    align_proc
    _div proc FASTCALL (VOIDARG) a:ptr real8, b:ptr real8
    	fld		real8 ptr [a]
    	fdiv	real8 ptr [b]
    	fstp	real8 ptr [a]
    	ret
    _div endp
    
    align_proc
    main proc C argc:dword, argv:ptr, environ:ptr
    local level:dword, EndPtr:ptr char, stack_oper@end:dword
    local stack_value[MAX_STACK]:real8, stack_oper[MAX_STACK]:stOperation
    local func_token[256]:stOperation
    order		= 2
    	printf("Calculator expression.\n")
    	lea		edi, func_token
    	ASSUME	edi:ptr stOperation, ebx:ptr char
    	;обнулим массив func_token
    	@MEMSET	(edi, 0, sizeof func_token)
    	lea		edi, [edi+'*'*8]
    	mov		[edi+'+'*8-'*'*8].func, offset _add
    	mov		[edi+'-'*8-'*'*8].func, offset _sub
    	mov		[edi+'*'*8-'*'*8].func, offset _mul
    	mov		[edi+'/'*8-'*'*8].func, offset _div
    	or		[edi+'+'*8-'*'*8].priority, 1
    	or		[edi+'-'*8-'*'*8].priority, 1
    	or		[edi+'*'*8-'*'*8].priority, 2
    	or		[edi+'/'*8-'*'*8].priority, 2
    	mov		level, ecx
    	;удалим пробелы
    	ASSUME	esi:ptr char
    	mov		eax, argv
    	mov		ebx, [eax+1*4]
    	push	ebx
    	.for (esi=ebx ::ebx++, esi++)
    		.while ([esi]==' ' || [esi]==9)
    			inc		esi
    		.endw
    		mov		al, [esi]
    		mov		[ebx], al
    		.break .if (!al)
    	.endfor
    	pop		ebx
    	ASSUME	esi:ptr real8
    	lea		esi, stack_value[-8]	;
    	lea		edi, stack_oper[-8]		;
    	mov		stack_oper@end, edi
    	;mov		ebx, CSTR("18/(-7-(1+1))*3-(2+(1-2))/10.5*(10*10)")	;// для отладки в IDA Pro
    	.while (true)
    		.for (:[ebx]=='(':ebx++)
    			add		level, order
    		.endfor
    		invoke	crt_strtod, ebx, addr EndPtr
    		add		esi, 8
    		mov		ebx, EndPtr
    		fstp	[esi]
    		.for (:[ebx]==')':ebx++)
    			sub		level, order
    		.endfor
    		.if (![ebx])	;// строка закончилась
    			.for (:edi>stack_oper@end: edi-=8, esi-=8);	stack@dec (edi), stack@dec (esi)
    				invoke	[edi].func, addr [esi-8], addr [esi]
    			.endfor
    			mov		edx, level
    			sar		edx, 1	;/=order
    			.if (!edx)
    				mov		edx, argv
    				printf("%s = %.10f\n", [edx+1*4], [esi])
    			.else
    				push	edx
    				.if (sdword ptr edx>0)
    					;printf("There is no closing parentheses: %d\n", edx)
    					push	CSTR("There is no closing parentheses: %d",0Dh,0Ah)
    				.else
    					;printf("There is no opening parentheses: %d\n", edx)
    					push	CSTR("There is no opening parentheses: %d",0Dh,0Ah)
    				.endif
    				call	crt_printf
    				add		esp, 8
    			.endif
    			xor		eax, eax
    			ret
    		.endif
    		movzx	edx, [ebx]
    		mov		eax, func_token[edx*8].priority		;eax - priority
    		add		eax, level
    		.for (:edi>stack_oper@end && [edi].priority >= eax: edi-=8, esi-=8);	stack@dec (edi), stack@dec (esi)
    			push	eax
    			invoke	[edi].func, addr [esi-8], addr [esi]
    			pop		eax
    		.endfor
    		movzx	edx, [ebx]
    		mov		ecx, func_token[edx*8].func
    		.break .if(!ecx)
    		add		edi, 8
    		mov		[edi].func, ecx
    		mov		[edi].priority, eax
    		inc		ebx
    	.endw
    	ASSUME	ebx:nothing, edi:nothing, esi:nothing
    	printf("unknown token '%c'\n", edx)
    	xor		eax, eax
    	inc		eax
    	ret
    main endp
    
    end mainCRTStartup

     

     

    Скачать UASM

    http://www.terraspace.co.uk/uasm.html

    Батник

    Скрытый текст
    
    @echo off
    
    ..\..\..\uasm246_x86\bin\uasm32 /c /coff "calc.asm"
    ..\..\..\uasm246_x86\bin\polink /SUBSYSTEM:CONSOLE "calc.obj"
    
    if exist "calc.obj" del "calc.obj"
    pause

     

    Линкер polink позволяется создавать компактные файлы. В нашем случае всего 1.5 кб.

     

    А теперь С++.

    Скрытый текст
    
    // Консольное утилита для вычисления выражений		(c) NanoBot
    #include <iostream>
    #define	MAX_STACK	128
    #define	order		2
    
    void __fastcall add(double *a, double *b) { *a += *b; }
    void __fastcall sub(double *a, double *b) { *a -= *b; }
    void __fastcall mul(double *a, double *b) { *a *= *b; }
    void __fastcall div(double *a, double *b) { *a /= *b; }
    
    int main(int argc, char** argv) {
    	struct stOperation {
    		void	set(void (__fastcall *f)(double *,double *), int p) { this->func = f; this->prior = p; };
    		void (__fastcall *func)(double *a, double *b);
    		int		prior;
    	}		TokFunc[128], stack_oper[MAX_STACK], *spOper = &stack_oper[-1], *stack_oper_end = spOper;
    	double	stack_value[MAX_STACK], *spValue = &stack_value[-1];
    	int		level=0, prior;
    	memset(TokFunc, 0, sizeof(TokFunc));
    	TokFunc['+'].set(add, 1); TokFunc['-'].set(sub, 1); TokFunc['*'].set(mul, 2); TokFunc['/'].set(div, 2);
    	printf("Calculator expression.\n");
    	for (char* p0 = argv[1], *p1 = p0; ; p0++, p1++) {
    		while(*p1==' ' || *p1==9) ++p1;
    		*p0 = *p1;
    		if(!*p1) break;
    	}
    	for (char* pStr = argv[1]; ; ++pStr) {
    		for (; *pStr == '('; level += order, ++pStr);
    		*++spValue = strtod(pStr, &pStr);
    		for (; *pStr == ')'; level -= order, ++pStr);
    		if (!*pStr) break;	// строка закончилась
    		char	token = !(*pStr&(~0x7F)) ? *pStr : 0;	// ограничем токены кодами 0..127
    		prior = TokFunc[token].prior + level;
    		for (; spOper>stack_oper_end && spOper->prior >= prior; spOper--, spValue--)
    			spOper->func(&spValue[-1], &spValue[0]);
    		auto 	f = TokFunc[token].func;
    		if (!f) { printf("unknown token '%c'\n", *pStr); return 1; }
    		(++spOper)->set(f, prior);
    	}
    	for (; spOper>stack_oper_end; spOper--, spValue--)
    		spOper->func(&spValue[-1], &spValue[0]);
    	if(!level)
    		printf("%s = %.10f\n", argv[1], *spValue);
    	else if((level/=order)>0)
    		printf("There is no closing parentheses: %d\n", level);
    	else
    		printf("There is no opening parentheses: %d\n", level);
    	return 0;
    }

     

     

    Весит 7.5 кб если использовать VS2010, с VS2017 весит 9.5 кб и не работает на ХР.

    Так что к чёрту std cout и другую хрень.

    В 09.06.2018 в 20:41, Malandrinus сказал:

    Код на ассемблере будет работать на конкретной платформе.

    Будет работать на конкретным процессоре. Это не очень актуально, ибо есть только х86 и х64, остальные меня не интересуют, в точности ARM.

    Изменено пользователем НаноБот

    ...в конце концов, важен лишь, машинный код.

    СТАЛКЕР только для ПК!

    Ссылка на комментарий

    Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

    Комментарии могут оставлять только зарегистрированные пользователи

    Создать аккаунт

    Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

    Зарегистрировать новый аккаунт

    Войти

    Есть аккаунт? Войти.

    Войти
    • Недавно просматривали   0 пользователей

      Ни один зарегистрированный пользователь не просматривает эту страницу.

    AMK-Team.ru

    ×
    ×
    • Создать...