1. 1C / Говнокод #25336

    +2

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    ВЫБРАТЬ
    КОЛИЧЕСТВО ( РАЗЛИЧНЫЕ УвольнениеИзОрганизации.Сотрудник) КАК Сотрудник
    Кадровая история сотрудников спецслужб их.Подразделение,
    ЕСТЬNULL (КОЛИЧЕСТВО ( РАЗЛИЧНЫЕ ВЫБОР
    КОГДА УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование = "" По собой желанию, на учебу пункт 3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" По соб желанию, по уходу за инвалидном п.3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование = "" По соб желанию, ребёнок-инвалид до 18 л., А 3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" По соб желанию , с переменой м. ж.,  пункт 3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" По соб желанию, по уходу за ребенком до 14 лет, п 3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" По соб желанию , на пенсию, п 3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" по соб желанию, п.3 статьи 77 ТК РФ""
    ТОГДА УвольнениеИзОрганизаций.Сотрудник
    КОНЕЦ ), 0) КАК увПоСобств,
     ЕСТЬNULL (ВЫБОР
     
    КОГДА УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" За прогулы, подпункт """" а"""" пункта 6 статьи 81 ТК РФ""
    ТОГДА УвольнениеИзОрганизаций.Сотрудник
    КОНЕЦ ,0) КАК УвПрогул,
    ЕСТЬNULL ( КОЛИЧЕСТВО ( РАЗЛИЧНЫЕ УвольнениеИзОрганизации.Сотрудник
    ),0) Как УвВсего
    ИЗ Документ.Увольнение.Сотрудник КАК УвольнениеИзОрганизации
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних как КадроваяИсторияСотрудниковСрезПоследних
    ПО Сотрудник КАК УвольнениеИзОрганизации.Сотрудник = КадроваяИсторияСотрудниковСрезПоследних.Сотрудник 
    ГДЕ 
    УвольнениеИзОрганизации.Ссылка.Организации в ИЕРАРХИИ (& Организация)
    И УвольнениеИзОрганизации.ДатаУвольнения >=& НачалоГода
     И (УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" По соб желанию, по уходу за инвалидном п.3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование = "" По соб желанию, ребёнок-инвалид до 18 л., А 3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" По соб желанию , с переменой м. ж.,  пункт 3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" По соб желанию, по уходу за ребенком до 14 лет, п 3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" По соб желанию , на пенсию, п 3 статьи 77 ТК РФ""
    ИЛИ УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" по соб желанию, п.3 статьи 77 ТК РФ""
    ИЛИ  УвольнениеИзОрганизаций.СтатьяТКРФ.Наименование ="" За прогулы, подпункт """" а"""" пункта 6 статьи 81 ТК РФ""
    ) 
    СГРУППИРОВАТЬ ПО
    КадроваяИсторияСотрудниковСрезПоследних.Подразлеление
    ЕСТЬNULL (ВЫБОР 
    КОГДА Увольнение Зоран зайти.СтатьяТКРФ.Наименование = "" За прогулы, подпункт """" а"""" пункта 6 статьи 81 ТК РФ""
    ТОГДА УвольнениеИзОрганизации.Сотрудник 
    КОНЕЦ ,0);

    Зачем ему конфигуратор? Он и так может отчеты выводить в табДок через блокнот)))
    Ссылка на источник ТУТ - http://www.cyberforum.ru/1c/thread2394049.html

    Запостил: dethmontt, 29 Января 2019

    Комментарии (137) RSS

    • > ЕСТЬNULL

      NULL есть? А если найду?
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • По-моему нормальный запрос. Ошибки вот:
      1. В строке 02 в конце строки не хватает запятой;
      2. Для увПоСобств в условии ВЫБОР не хватает ИНАЧЕ;
      3. В строке 36 в конце строки не хватает запятой;
      4. В последней строке (в СГРУППИРОВАТЬ ПО) в условии ВЫБОР не хватает ИНАЧЕ;
      5. В последней строке, в конце строки точка с запятой не нужна.
      Ответить
      • Искать по наименованию такие сложные фразы нормально? Какой-нибудь лишний пробел перед запятой (как в строке 8) уберут и приехали...
        Ответить
        • Здесь нигде не написано, что эти наименования пишут руками, или они допустимы для редактирования пользователями
          Ответить
          • Х.з., у меня просто после с++ деформация сознания, всегда оцениваю худший вариант... Если явно не написано, что юзер не может менять - значит он может поменять.
            Ответить
          • > собой желанию
            > уходу за инвалидном
            Походу таки руками :)
            Ответить
      • показать все, что скрытоvanished
        Ответить
    • По соб желанию , с переменой м->ж

      fuxed
      Ответить
    • Кавычки! Кавычки!!! Они слишком быстро размножаются! Мы не сможем их долго сдерживать, бегите!!!"""""""""""'"""""" АРРАРРРАРГХ""""""""""""АААРААРРРРРРРГХ"" """"""""""""
      Ответить
      • Со слешами та же фигня...
        Ответить
        • В «Python» ничего такого есть «r». Именно поэтому я за «Python».
          Ответить
          • Блять, не могу нагуглить как называется, была такая поебень (в древнем "Фортране"?) где указывалось число символов в строке. Именно поэтому я за "Фортран".
            Ответить
            • В пэхапэшной сериализации указывается размер каждого элемента:
              <?php
              $s = 'Кукареку';
              $q = serialize($s);
              echo $q;


              Выводит:
              s:16:"Кукареку";

              Тут размер в байтах.

              Пруфлинк: https://ideone.com/YqKWVf

              Именно поэтому я за "PHP".

              Ещё в заголовках торрент-файлов (bencode) тоже перед строкой указывается её размер.

              Где-то ещё было, но мой петушиный мозг сходу не может вспомнить. Точно ещё где-то было, это же не могло мне присниться.
              Ответить
              • > В пэхапэшной сериализации указывается размер каждого элемента:
                А зачем? В контексте эскейпа это никак не поможет: в (5, "\r\nab") всё равно будет неоднозначность. А в контексте нулевых байт — ну дык «serialize()» по-любому должна бинарные данные эскейпить и выводить нуль-терминированную строку, или я что-то своим мозгом по ГОСТу не понимаю?
                Ответить
                • Да, вынужден согласиться, что в пэхапэшной сериализации говно: парсеру оно никак не поможет. Этот размер помогает только аллокатору выделить память.
                  Ответить
          • показать все, что скрытоvanished
            Ответить
            • В «Python» есть «r''' '''» и даже «r""" """». Но согласен, экранирование кавычек там хуёвое.
              Ответить
            • показать все, что скрытоvanished
              Ответить
            • показать все, что скрытоvanished
              Ответить
              • Давай!
                Ответить
              • И мне тоже расскажите про фрактал плохого дизайна, пожалуйста.
                Ответить
                • показать все, что скрытоvanished
                  Ответить
                  • Гуглится про «PHP», а я хочу про «Python».
                    Ответить
                    • Многие wtfы из фрактала плохого дизайна «PHP» давно уже пофиксили и они неактуальны.

                      Например вот этот пиздец:
                      0x0+2 produces 4. 
                      
                      The parser considers the 2 as both part of the hex literal and a separate decimal literal, treating this as 0x002 + 2. 0x0+0x2 displays the same problem. 
                      
                      Strangely, 0x0 +2 is still 4, but 0x0+ 2 is correctly 2. (This is fixed in PHP 5.4. But it’s also re-broken in PHP 5.4, with the new 0b literal prefix: 0b0+1 produces 2.)
                      Ответить
                      • Как вообще можно написать парсер, который может отнести один символ к джвум разным токенам одновременно?!
                        Ответить
                        • Чисто теоретически:
                          разбирают выражение, находят +, начинают разбирать аргументы, тут почему-то получается так, что аргумент парсится из той же строки, что и изначальное выражение. То есть первый аргумент плюса это не 0x0, а 0x0+2. Как такое может быть? Ну может они там с индексами ебутся, а не копируют кусочки строк для оптимизации...

                          > fixed in PHP 5.4 [...] re-broken in PHP 5.4, with the new 0b literal
                          - скопировать юнит-тест религия не позволила конечно же
                          Ответить
                          • Так и есть. Парсер после 0x сначала глотает все нолики, потом функции strtol передаёт основание системы счисления (в данном случае 16) и указатель на первый символ подстроки, из которой нужно извлечь число. Функция strtol жадная, она глотает максимальное кокококоличество символов, кокококоторые являются валидными для числа.
                            Ответить
                            • Точнее так: после съедания ноликов первым символом окажется '+' или ' ' strtol их успешно проглотит, потому что ничего не знает о длине токена, длина ей не передаётся (сишкостроки, привеет!), но пхпшный парсер числа не знает, сколько она съела, и продолжает дальше парсить с '+'. Т.е. лексер распарсит из строки "0x0+2" «токен» "0x0+2" проинтерпретирует его как 2, затем "+", а затем уже "2".

                              Какой "C" )))
                              Ответить
                            • Да уж, в этом смысле лисп рулит. Там не выйдет прилепить операнды к оператору и получить парсеропроблемы
                              Ответить
                            • А так-то конечно звиздец: нашли токен, скормили его произвольной функции, после нас хоть потоп.
                              Ответить
                              • > его
                                Если бы они его скормили, то всё норм было бы. А они хуйню за токеном скормили.
                                Ответить
                                • С точки зрения разработчиков парсера пыхи, судя по всему, токен это указатель на подстроку
                                  Ответить
                        • Исходники открыты:

                          https://git.php.net/?p=php-src.git;a=blob;f=Zend/zend_language_scanner.l;hb=refs/heads/PHP-5.3

                          https://git.php.net/?p=php-src.git;a=blob;f=Zend/zend_language_parser.y;hb=refs/heads/PHP-5.3

                          Упоминание "0x" встречается в таких фрагментах:
                          HNUM	"0x"[0-9a-fA-F]+

                          <ST_IN_SCRIPTING>{HNUM} {
                          	char *hex = yytext + 2; /* Skip "0x" */
                          	int len = yyleng - 2;
                          
                          	/* Skip any leading 0s */
                          	while (*hex == '0') {
                          		hex++;
                          		len--;
                          	}
                          
                          	if (len < SIZEOF_LONG * 2 || (len == SIZEOF_LONG * 2 && *hex <= '7')) {
                          		zendlval->value.lval = strtol(hex, NULL, 16);
                          		zendlval->type = IS_LONG;
                          		return T_LNUMBER;
                          	} else {
                          		zendlval->value.dval = zend_hex_strtod(hex, NULL);
                          		zendlval->type = IS_DOUBLE;
                          		return T_DNUMBER;
                          	}
                          }


                          В новой версии добавили проверку длины на ноль:
                          +		if (len == 0) {
                          +			Z_LVAL_P(zendlval) = 0;
                          +		} else {
                          +			Z_LVAL_P(zendlval) = strtol(hex, NULL, 16);
                          +		}
                          Ответить
                          • Ещё вот тут:
                            case 'x':
                            				case 'X':
                            					if (ZEND_IS_HEX(*(s+1))) {
                            						char hex_buf[3] = { 0, 0, 0 };
                            
                            						zendlval->value.str.len--; /* for the 'x' */
                            
                            						hex_buf[0] = *(++s);
                            						zendlval->value.str.len--;
                            						if (ZEND_IS_HEX(*(s+1))) {
                            							hex_buf[1] = *(++s);
                            							zendlval->value.str.len--;
                            						}
                            						*t++ = (char) strtol(hex_buf, NULL, 16);
                            					} else {
                            						*t++ = '\\';
                            						*t++ = *s;
                            					}
                            					break;
                            Ответить
                            • И вот тут:
                              if (ZEND_IS_DIGIT(*ptr)) {
                              		/* Handle hex numbers
                              		 * str is used instead of ptr to disallow signs and keep old behavior */
                              		if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
                              			base = 16;
                              			ptr += 2;
                              		}
                              
                              		/* Skip any leading 0s */
                              		while (*ptr == '0') {
                              			ptr++;
                              		}
                              
                              		/* Count the number of digits. If a decimal point/exponent is found,
                              		 * it's a double. Otherwise, if there's a dval or no need to check for
                              		 * a full match, stop when there are too many digits for a long */
                              		for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors == 1)); digits++, ptr++) {
                              check_digits:
                              			if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) {
                              				continue;
                              			} else if (base == 10) {
                              				if (*ptr == '.' && dp_or_e < 1) {
                              					goto process_double;
                              				} else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
                              					const char *e = ptr + 1;
                              
                              					if (*e == '-' || *e == '+') {
                              						ptr = e++;
                              					}
                              					if (ZEND_IS_DIGIT(*e)) {
                              						goto process_double;
                              					}
                              				}
                              			}
                              
                              			break;
                              		}
                              
                              		if (base == 10) {
                              			if (digits >= MAX_LENGTH_OF_LONG) {
                              				dp_or_e = -1;
                              				goto process_double;
                              			}
                              		} else if (!(digits < SIZEOF_LONG * 2 || (digits == SIZEOF_LONG * 2 && ptr[-digits] <= '7'))) {
                              			if (dval) {
                              				local_dval = zend_hex_strtod(str, (char **)&ptr);
                              			}
                              			type = IS_DOUBLE;
                              		}
                              	} else if (*ptr == '.' && ZEND_IS_DIGIT(ptr[1])) {

                              https://git.php.net/?p=php-src.git;a=blob;f=Zend/zend_operators.h;hb=refs/heads/PHP-5.3
                              Ответить
                              • показать все, что скрытоvanished
                                Ответить
                              • А функция преобразования шестнадцатеричной кокококонстанты в целого питуха написана в лучших традициях сишки.
                                ZEND_API double zend_hex_strtod(const char *str, char **endptr)
                                {
                                	const char *s = str;
                                	char c;
                                	int any = 0;
                                	double value = 0;
                                
                                	if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) {
                                		s += 2;
                                	}
                                
                                	while ((c = *s++)) {
                                		if (c >= '0' && c <= '9') {
                                			c -= '0';
                                		} else if (c >= 'A' && c <= 'F') {
                                			c -= 'A' - 10;
                                		} else if (c >= 'a' && c <= 'f') {
                                			c -= 'a' - 10;
                                		} else {
                                			break;
                                		}
                                
                                		any = 1;
                                		value = value * 16 + c;
                                	}
                                
                                	if (endptr != NULL) {
                                		*endptr = (char *)(any ? s - 1 : str);
                                	}
                                
                                	return value;
                                }
                                Ответить
                                • ZEND_API означает, что эту функцию можно будет вызвать прямо из пыхокода (с использованием zend?) ?

                                  Мне нравится, что функции в принципе пофиг, есть в начале строки 0x или нет. Оно понятно, что функция, например, выше, которая вызывает zend_hex_strtod, ещё и сама стрипает префикс, потому пришлось так сделать, но... ёбтваюмать. Зачем тащить это в паблик
                                  Ответить
                                  • Впрочем, как оказалось, у strtol ровно такое же поведение.

                                    Вопрос тогда, зачем стрипать 0x отдельно уровнем выше, когда и strtol, и самописная функция его прохавают
                                    Ответить
                                  • Чтобы вызывать функцию из пыхокода, её нужно описывать по-другому:
                                    https://www.php.net/manual/ru/internals2.funcs.php

                                    Если мы хотим из пыхокода вызывать функцию как hex_strtod, то нужно объявить такую функцию:
                                    void zif_hex_strtod(int ht, zval* return_value, zval** return_value_ptr, zval* this_ptr, int return_value_used);

                                    Пышечка в первый параметр (ht) положит количество реальных аргументов (в данном случае скорее всего 1), во второй параметр (return_value) положит указатель на область памяти, в которую наша функция должна сохранить результат. Извлекать аргументы наша функция должна сама, используя вызов zend_parse_parameters.

                                    Короче, обёртку нужно дописать, чтобы вызвать из пыха.
                                    Ответить
                                    • А zend_api тогда просто cdecl какой-нибудь?
                                      Ответить
                                      • Похоже, какая-то шняга для расширения самого пхп. Судя по всему, deprecated.

                                        https://www.php.net/manual/en/internals2.ze1.zendapi.php
                                        Ответить
                              • показать все, что скрытоvanished
                                Ответить
                      • показать все, что скрытоvanished
                        Ответить
                    • показать все, что скрытоvanished
                      Ответить
                      • Ещё спрашиваешь! А для чего этот сайт, если не для говна?
                        Ответить
                        • показать все, что скрытоvanished
                          Ответить
                          • показать все, что скрытоvanished
                            Ответить
                          • >> Типизация как-бы чисто динамическая, но на самом деле ты всегда должен знать тип.
                            >> если data это list, а id вдруг пришла как строка ('1' а не 1), то ты соснул, бо типизация строга.

                            Напоминает «Object Pascal» (в частности, «Delphi»): там есть динамический тип Variant, в который можно пихать данные произвольных типов (ибо там есть поле-дескриптор, которое помнит, значение какого типа сейчас лежит в переменный), но неявного каста нет (ибо типизация строгая), поэтому нужно либо явно кастовать (и это на мой взгляд хорошо), либо в функции, принимающей Variant, делать свитч по всем допустимым типам.

                            Однако, в «Object Pascal» динамическая типизация опциональная: ты явно указываешь переменные, которые принимают динамический тип. А в «Питоне» динамическая типизация повсюду.
                            Ответить
                          • Сам питон на аннотации срал, ему похуй даже когда они есть, они нужны для линтеров и иде. Будет тебе нечто типа статической типизации.

                            > Есть itertools, а есть list comprehension. Что и когда юзать?
                            Попробуй мне вырази хоть одну функцию из itertools одним компрехеженом.

                            > next(map(lambda p: age,filter(lambda p: p.name == "rebeshok", petushki)))
                            Понял, что написал? Эквивалентно просто:
                            age
                            Ладно, сам переведу первую версию:
                            next(p.name == "grepeshok" for p in petuji).age
                            Ответить
                            • Ну вот теперь я обосрлся:
                              next(p for p in putishki if p.name == "grebeshol"). age
                              fixed
                              Ответить
                    • показать все, что скрытоvanished
                      Ответить
                      • А с Виндой что не так?
                        Ответить
                        • показать все, что скрытоvanished
                          Ответить
                        • показать все, что скрытоvanished
                          Ответить
                          • # -*- coding: cp866 -*-
                            print "Привет, мир!"

                            Сам исходник, естественно, в досовской кодировке, как bat-файлы.

                            Если выполнить CHCP 1251, то можно исходник перевести в виндовую кодировку:
                            # -*- coding: windows-1251 -*-
                            print("Привет, мир!")

                            Но не нужно, ибо после CHCP 1251 обычные bat-файлы будут выводить кракозябры.

                            Да, в третьем Питоне работают оба варианта без CHCP.
                            Ответить
                            • показать все, что скрытоvanished
                              Ответить
                              • Попробовал переназначить вывод через >.

                                В двойке всё высралось в кодировке исходника, в тройке — в виндовой (cp1251) вне зависимости от кодировки исходника.

                                *****

                                После CHCP 65001 двойка вообще глючит по-страшному:
                                ��ривет, мир!Traceback (most recent call last):
                                  File "c.py", line 2, in <module>
                                    print("Привет, мир!")
                                IOError: [Errno 2] No such file or directory

                                При перенаправлении вывода в файл всё работает.

                                *****

                                Тройка при перенаправлении сосноли в файл не хочет выводить юникодный текст, даже если исходник в UTF-8. Пробуем вывести греческую букву «альфа»:
                                # -*- coding: utf-8 -*-
                                print("⍺")

                                Результат в stderr:
                                Traceback (most recent call last):
                                  File "d.py", line 2, in <module>
                                    print("\u237a")
                                  File "C:\Python36\lib\encodings\cp1251.py", line 19, in encode
                                    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
                                UnicodeEncodeError: 'charmap' codec can't encode character '\u237a' in position 0: character maps to <undefined>


                                Просто в сосноль выводит нормально.

                                Зачем в тройке хакнули перенаправление сосноли в файл?
                                Ответить
                      • > Назвал переменную str? Получи вылет после вызова
                        В "PHP" у пелременных и функций отдельные неймспейсы. Именно поэтому я за "PHP".
                        Ответить
                    • показать все, что скрытоvanished
                      Ответить
              • Считается ли фракталом пустое множество?
                Ответить
      • показать все, что скрытоvanished
        Ответить
    • за Наименование ="" вообще казнь надо ввести.
      Ответить
      • Простите, а как надо?
        Ответить
      • Скорее всего весь этот кот находится внутре строкококого литрала.
        Ответить
    • Меня мучает вопрос: почему везде после кавычки пробелы?
      Ответить
      • S" форт" ?
        Ответить
        • Возможно автор тоже любит в свободное время с ним побаловаться.

          Кстати, после закрывающей кавычки пробел не нужен, ' S" установит ' >IN на символ за кавычкой. Но без него как-то неспокойно на душе...
          Ответить
          • Блин, что-то захотелось форт вспомнить. Запилить что-ли под ту ARM'овскую плату. Можно ps/2 клаву и няшный дисплейчик туда подрубить...
            Ответить
            • > ps/2 клаву и няшный дисплейчик туда подрубить
              А можно просто эту пллату через USB к конпуктеру подключить и юзать его как терминал. Вот только лень с этим розбираться... Я пока что моргатель светодиодами :(
              Ответить
              • Ну терминал через UART - тоже годный вариант.
                Ответить
              • З.Ы. Или ты прям как USB девайс хотел её в комп воткнуть? Можно, но это на порядок сложнее UART'а...
                Ответить
                • Да я это и имел ввиду, а про UART я что-то и не подумал, видимо потому что как раз недавно читал статью про USB и зациклился на нём.
                  Ответить
              • Блин, насколько непривычно писать в машинных кодах под эти ARM'ы...

                Зато фортовый next для direct threading в одну инструкцию получился: ldmia r7!, {pc} (в r7 лежит указатель на шитый код).
                Ответить
                • Пиши на "gforth", у него есть ассемблеры для разных архитектур:
                  http://gforth.org/manual/ARM-Assembler.html#ARM-Assembler
                  s" arch/arm/asm.fs" included
                  here
                  r7 ia! { pc } ldm,
                  here over - dump
                  Ну или свой пишешь. Ассемблер просто конпелирует инструкции в область данных. Собираешь образ и выводишь в файл.

                  Вообще да, для x86 инструкции можно собирать по байтам, а для армов приходится по битам.
                  Ответить
                  • Отдельное "ia!" смешное :)
                    Ответить
                  • Да мне просто интересно разобраться, как там инструкции кодируются, поэтому асм сам пилю.

                    И пока thumb2 не особо радует - там переменная длина инструкций (16 бит или 2 раза по 16 бит), по 2-3 формы для каждой инструкции, везде разные длины immediate и куча алиасов между инструкциями...

                    Даже х86 местами логичней кажется.
                    Ответить
                    • А на нём можно писа́ть в ASCII-кодах?
                      Ответить
                      • Х.з., давай посмотрим.
                        Ответить
                      • Доступны будут только инструкции thumb1, которые кодируются джвумя байтами. У четырёхбайтных thumb2 первый байт как минимум 0xE0.

                        К примеру, 0x48..0x4F ('H'..'O') упали на команду LDR. "H " загрузит в R0 dword, который лежит через 32 байта от текущей инструкции. "I " - в R1. И т.п.

                        EOR (аля XOR) мапается на 0x40 ('@'). Во втором байте должно быть 01SSSDDD. Т.е. почти все варианты с регистрами с r0 по r7 доступны (eor r7, r7 выпадает т.к. в ascii нет 0x7F). Всякие сложения-вычитания - аналогично.

                        BX (аля jmp на регистр) попал на 0x47 ('G'), во втором байте надо 0RRRR000, т.е. все регистры от R0 до R15 доступны.

                        STR Rt, [Rn + Rm] попадает на 0x50 и 0x51 ('P', 'Q'). Кодируется как 0101000M MMNNNTTT. Т.е. от M будет доступно где-то 4 регистра.

                        В целом - неплохо.
                        Ответить
                      • Жопа в том, что первые 2 слова прошивки должны содержать стартовые значения SP и PC соответственно. Хер с ним, с SP. Но флешка замапана на 0x00000000 и на 0x08000000. Т.е. валидный адрес для PC из ascii никак не слепить :(
                        Ответить
                        • Зато можешь писать:
                          s" <тута код>" drop execute ( если оно у тебя ожидает адрес кода )
                          Но ещё инструкции для работы со стеком недоступны и бранчи.
                          Ответить
                          • Бранчи легко сделать через арифметику и BX. Стек можно замутить вручную на нижних регистрах через LDR/STR + ADD/SUB.
                            Ответить
                          • > s"
                            Кстати, вспомнил тут свою давнюю идею - фортоподобный язык, где слова не надо отделять пробелами. Тупо искать самое длинное совпадение в словаре. Пробел, таб и возврат каретки - пустые слова, которые ничего не делают. Цифры инициируют парсинг числа, кавычки - парсинг строки и т.п. Само собой, ты можешь всё это поменять т.к. это просто записи в словаре.
                            Ответить
                            • > Цифры инициируют парсинг числа, кавычки - парсинг строки
                              Типа как в 'RETRO_FORTH префиксы? Вот только слова там пробелами отделяются, 'поэтому_строки_выглядят_вот_так. Ещё у тебя придётся убрать/переименовать слова типа: 1+ 1- 2dup 2@ 2! 2+ 2*. А мне нравится разделение пробелами, парсер простой получается. Если пробел после кавычки мозолит глаза, для строк можно придумать такой синтаксис:
                              s "Привет, bormand!"
                              Я это даже где-то постил.

                              У меня, кстати, тоже своя идея есть, я даже её наполовину запилил, но потом забросил (ну ядро в виде com файла давно уже пылится, почти допиленное, хотел допилить и переписать на самом себе под 32 бита, но надоело):
                              1. Определяющие слова не сами парсят имена, а принимают их параметрами на стеке. Например : принимает адрес, длину, создаёт определение, начинает компиляцию. Код получается вербознее, но зато проще в своих определяющих словах проверять имя на что-то ( например, что слово уже определено или на какой-то ограничитель, типа как locals| ... | ), или создавать генеренные слова.
                              2. Ещё работа некоторых слов пересмотрена, например word не ожидает символ-разделитель в стеке, а сразу парсит имя ( не знаю нахер оно в стандарте пропускает ведущие разделители, кроме как для парсинга имён оно ни для чего не годится), и возвращает не адрес строки со счётчиком, а как parse адрес и длину. Соответственно find принимает не адрес строки со счётчиком, а адрес и длину.
                              3. Для неопределённого слова система не пытается преобразовать его в число, а передаёт его подпрограмме, адрес которой хранится в переменной 'not-found, по умолчанию там подпрограмма которая выводит сообщение об ошибке.
                              4. Чтобы записать число нужно использовать слово # оно распарсит число из исходника ( хочу заменить стандартное # которое юзается в <# ... #> на % или _ но пока не решил )
                              5. Ну ещё некоторые слова переименовал ( invert - not postpone - compile then - end-if begin - loop repeat - end-while )
                              Ответить
                              • Часть я на нём самом написал, вот пример:
                                word find' : find ?dup (jmpnz) [ here 0 , ] (not-found) [ here over - swap ! ] ;
                                word get : find' drop ;
                                word ' : word get ;
                                word literal immediate: (push) [ ' (push) , ] compile, , ;
                                word ['] immediate: ' [ ' literal compile, ] ;
                                word if immediate: ['] (jmpz) compile, here 0 , ;
                                word end-if immediate: here over - swap ! ;
                                word else immediate: ['] (jmp) compile, here 0 , swap [ ' end-if compile, ] ;
                                word get-header : find-header 0= if (not-found) end-if ;
                                word header : word get-header ;
                                word (compile) : -1 = if [ ' literal compile, ] ['] compile, compile, else compile, end-if ;
                                word compile immediate: word find' (compile) ;
                                word loop immediate: here ;
                                word end-loop immediate: compile (jmp) here swap - , ;
                                word } : ;
                                word { immediate:
                                    loop
                                      word find' over ['] } = if 2drop exit end-if
                                      (compile)
                                    end-loop ;
                                word while immediate: { if } ;
                                word end-while immediate: swap { end-loop end-if } ;
                                word until immediate: { (jmpz) } here swap - , ;
                                word for immediate: { >r 2dup = if 2drop r-drop else 2>r loop } ;
                                word -for : 3 r-n-drop ;
                                word end-for immediate: { r> 2r@ rot + dup >r = until -for end-if } ;
                                word i immediate: { r@ } ;
                                word j immediate: { 3 r-pick } ;
                                word counter@ immediate: 3 * { literal r-pick } ;
                                word case immediate: 0 ;
                                word of immediate: 1+ { over = if drop } ;
                                word end-of immediate: { else } swap ;
                                word when immediate: 1+ { if } ;
                                word end-when immediate: { end-of } ;
                                word end-case immediate: 0 1 for { end-if } end-for ;
                                Но ещё не всё потестированно.
                                Ответить
                                • Это же вордоподобный язык!
                                  Ответить
                                • Ещё усложняло что я решил хуй наложить на проверку ошибок, так что дебажить очень сложно было, оно может молча хуйню выполнять пока совсем не распидорасит.
                                  Ответить
                                • Немножко пояснений:
                                  (jmpnz) -- выбирает из шитого кода слово, берёт число с вершины стека, если не ноль, прибавляет его к указателю инструкций шитого кода
                                  (jmpz) -- как (jmpnz) только условие противоположное
                                  (jmp) -- безусловный переход, стек не трогает

                                  (not-found) ( c-addr u -- ) выводит сообщение о том, что слово не найдено, вызывает quit

                                  (push) выбирает из шитого кода слово, увеличивает указатель инструкций на размер слова, пушит это слово на стек

                                  immediate: -- определяет immediate слово, как : hui ; immediate в форте

                                  r-drop -- убрать число со стека возвратов
                                  r-n-drop ( n -- ) -- убрать n чисел со стека возвратов
                                  r-pick ( n -- x ) как pick, только работает со стеком возвратов

                                  Всё остальное стандартное или описано выше.
                                  Ответить
                                  • Ещё забыл: для маленьких чисел определены константы, но я пока не решил сколько их должно быть, так что пока только для тех что я использовал.
                                    Ответить
                                    • Оптимизация чтобы на (push) не тратиться?
                                      Ответить
                                      • Ну и чтобы парсинг чисел тоже на нём самом написать, а числа-то нужны.
                                        Ответить
                                • Ебать поехавший
                                  Ответить
                                • Питух, а ты в yacc, bison или шото подобное умеешь?
                                  Ответить
                              • Хм, вспомнил ещё одну сложность: у меня были проблемы с does>
                                Ответить
                                • Там самая главная проблема, имхо, вообще понять что этот does> должен делать...
                                  Ответить
                                  • Ну, по идее create создаёт для слова примерно такой код:
                                    push @f
                                    next
                                    ; или call _create
                                    ; а _create выглядит так (если стек данных sp)
                                    ; _create:
                                    ;    next ; на стеке остаётся адрес данных
                                    
                                    ; за определением следуют данные
                                    @@:
                                    ; здесь произвольные данные
                                    а does> должен заменить код у определения созданного через create на код, следующий за does> в определении + код запушивающий адрес данных в стек. Если create компилит просто call то по идее надо заменить этот последний call на call кода за does>. Я это уже один раз делал, но это было давно и система вся сплошь из костылей состояла.
                                    Ответить
                              • Хм, может на "Си" переписать, и сделать VM как в RETRO? И тупо дампать память виртуальной машины, чтобы не ебаться с разными форматами файлов?
                                Ответить
                  • adr r1, test ; F20F 0100
                    test:
                    
                    adr r1, test ; A100
                    nop
                    test:
                    
                    nop
                    adr r1, test ; A100
                    test:
                    Метки, адрес которых не кратен 4, требуют длинную инструкцию. Какой багор )))
                    Ответить
                    • Даже у x86 с его хитрозапутанной системой команд такого не было.
                      Ответить
                      • Ну просто под immediate осталось всего 8 бит, а литералы обычно один хер выровнены. Вот решили немного увеличить диапазон и умножили на 4.

                        Это хуйня. Главное - к чему этот оффсет прибавляется: к адресу текущей инструкции плюс четыре округлённому вниз до кратного четырём.

                        Для ARM'а это выглядело нормально, там все инструкции по 4 байта, поэтому там это был просто адрес следующей инструкции... Но для thumb'а эта формула выносит мозг.
                        Ответить
                        • Мозг нинужен.
                          Ответить
                        • Кстати, MASM/TASM на x86 вносили небольшую путаницу: $ означал начало текущей инструкции, а у инструкций JMP SHORT (0EBH, 'ы' в cp866), JMP NEAR (0E9H, 'щ' в cp866), CALL NEAR (0E8H) и у всех условных переходов (Jxx SHORT, JCXZ, LOOPxx и даже Jxx NEAR) immediate отсчитывалось от следующего за инструкцией байта.

                          Т. е. JMP SHORT $+2 (аналог NOP, но медленнее) кодировалось как 0EBH, 00H, а JMP SHORT $+0 (бесконечный цикл) кодировалось как 0EBH, 0FEH.
                          Ответить
                          • > ОЕВН
                            Прочитал как ОВЕН.

                            > $+0
                            Х.з., мне всегда было проще метку написать.
                            Ответить
                            • 0BEH —– это MOV SI/ESI, IMM 16/32, значит 0BEH —– это его файка.
                              Ответить
                              • А если не мовать, а пушнуть, потом попнуть, потом снова пушнуть - оптимизируется ли такое говнецо?
                                Ответить
                                • Ассемблер ничего не оптимизирует. Именно поэтому я за "ассемблер".
                                  Ответить
                                  • „TASM“ меняет JMP NEAR на JMP SHORT, а CALL FAR на PUSH CS + CALL NEAR, но только если его об этом явно попросить.
                                    Ответить
                                  • нО БЫВАЮТ ЖЕ ОПТИМИЗИРУЮЩИЕ АССЕМБЛЕРЫ? я О СОФТИНЕ, НЕ ОБ ЯЗЫКЕ.
                                    Ответить
                                    • Разве что „C--“.

                                      Суть ассемблера в том, чтобы выдавать именно те инструкции, которые хочет видеть программист. Может быть, от подёргивания стека возникает какой-то побочный эффект?
                                      Ответить
                    • В "ARM" такой хуйни нет. Именно поэтому я за "ARM".
                      Ответить
                  • Кстати, а ведь фортовые килобайтные BLOCK'и неплохо согласуются с килобайтными страничками флеша на этой stm'ке...
                    Ответить
                    • Форт много с чем согласуется, он изначально рассчитан на standalone работу на всяких контроллерах, без ОС и без ФС. Поверх блоков можно и самому ФС намутить.

                      Кстати, в ранних реализациях в целях экономии слова отличались лишь по первым трём символам и длине, так что надо было быть аккуратнее. Я ещё придумал экономию: в памяти можно хранить лишь код, а сами статьи читать с флеша только при интерпретации исходного кода, ведь большее время работы они не нужны.

                      ЗЫ. как думаешь, искать в словаре не по строке, а по хэшу (например PJW-32) хорошая идея или плохая? При коллизиях как поступать, если найдено более одного подходящего слова сравнивать по строке или тупо выдать ворнинг при переопределении?
                      Ответить
                      • Да там вообще можно базовую систему хранить во флеше, а оперативку целиком оставить для юзера.

                        > хэшу
                        Зачем хеш при линейном поиске?
                        Ответить
                        • Чтоб сравнивать не строки, а числа. Оптимизация!

                          PJW-32 не годится, я уже нашёл коллизии в стандартном наборе слов: 0= 1-
                          :(
                          Ответить
                          • Строк с общим префиксом не так много, большая часть по 1-2 символам уже отлетит.

                            Оптимизацией были бы хешмап или дерево вместо списка.
                            Ответить

    Добавить комментарий