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

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

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

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

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