Курилка программистов - Страница 51 - Скрипты / конфиги / движок - AMK Team
Перейти к контенту

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


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

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 сек,

 

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

 

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

В 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:

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

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

Мне не нравится С++, особенно С++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 студия уже не позволяет ?

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

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 пользователей

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