1. Си / Говнокод #26942

    +6

    1. 1
    2. 2
    #define add(x, y) &((void*)x)[y];
    #define mul(x, y) (sizeof (char[x][y]))

    из свитера

    Запостил: 3.14159265, 10 Сентября 2020

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

    • Откуда?
      Ответить
    • показать все, что скрытоvanished
      Ответить
      • А я до сих пор не понял
        Ответить
        • Теперь понял.
          Ответить
        • хинт: адрисняя арифметика
          Ответить
          • Зачем ты слово «дрисня» окружил какими-то лишними буквами?
            Ответить
            • "адрисняя" отвечает на вопрос "что делая?"
              Ответить
              • Закончив кидать, он напился воды,
                Воды одриснённой, нечистой.
                С лица его падал пот, сажи следы,
                Услышал он речь машиниста.
                Ответить
      • >нихуя не понел

        https://godbolt.org/z/YaKK8P
        Ответить
      • Боишься NullPointerException?

        Тут же нет разыменования: мы берём & от данных, а с самими данными ничего не делаем.
        Ответить
        • не боюся, уже понел, что это только про адреса
          а чтобы я еще лучше понял, мне пи lea показал
          Ответить
    • Поясни что это за хуета, Пи.
      Ответить
      • Единственная полезная структура данных — массив.
        Ответить
    • Погромист, который видел инструкцию LEA у «x86», даже не удивится.
      Ответить
    • Продолжим изучать ценность структуры «массив»
      Ответить
      • Ничего не напутано? Ложному условию соответствует нулевое смещение массива, истинному — смещение 1. Либо убрать один восклицательный знак, либо поместать менями true и false.
        Ответить
        • Да. Напутано.
          Ответить
        • https://ideone.com/7ZUAU4
          #define ternary(cond, true, false) ( (void *[]){true,false}[!cond] )
          Ответить
          • В «крестах» не конпелируется, потому что true и false заняты под ключевые слова.
            Ответить
            • >В «крестах» не конпелируется
              Так сказано, будто это что-то плохое.

              Кстати первая версия и в сишке не компилилась.

              Я второпях забыл что в compound literals нужно ставить скобки вокруг типа.
              Ответить
              • Оказывается, не из-за true и false. В крестах более строгая проверка типов. Обойти её с помощью гнутого расширения typeof мне пока тоже не удалось.
                Ответить
            • Он специально так назвал, чтобы выебнуться.
              Ответить
            • Что???

              Даже в препроцессоне?
              Ответить
    • А pow слабо?
      Ответить
      • Меня не меньше интересует, можно ли реализовать деление.
        Ответить
        • Да, и не столько деление, а тьюринг-полные вещи вообще.
          if уже есть.

          Деление можно будет и скобенировать.
          Ответить
        • Вроде недавно писали, что можно умножить и прибавить по модулю 2^32.
          Ответить
          • Это я писал.

            Мысль хорошая. Но там ещё финальный сдвиг вправо нужен.
            Ответить
          • https://ideone.com/sNzX8P

            printf("%d",(6L*1431655766L)>>32); //деление на 3

            Только это на константу.
            Для пельменных так не получится.
            Ответить
        • Пытался сделать деление на 4.

          Пока что не могу откастить массив int32_t в массив char
          union {
          	int32_t ints[500];
          	char bytes[];
          } addr;
          
          	printf ("%d",(&addr.bytes)[1] - addr.bytes);


          Я уже в struct их пихал, чтобы сделать flexible array member.
          Ответить
      • >А pow слабо?
        Думаю через вложенные макросы и массивы массивов массивов это реализуемо.
        Дерзай.
        Ответить
        • С фиксированным показателем степени просто. Например, куб — это sizeof(char[x][x][x]).

          Переменный показатель можно реализовать рекурсией. Но это уже не то...

          Постоянное основание иногда можно реализовать через сдвиги. Но как вытянуть сдвиги из указателей, я не знаю.

          В общем случае можно двойку возводить в степень произведения показателя на логарифм основания по основанию 2. Но если основание не является степенью двойки, вылезет плавпитух... Ну и опять же, как вытянуть этот логарифм, я не знаю.
          Ответить
    • #define add(x, y) sizeof(struct{char X[x], Y[y]})
      Ответить
    • #include <stdio.h>
      
      struct Array
      {
          int a;
          char bytes[];
      }; 
      
      typedef struct Array Array;
      
      union {
          int ints[500];
          Array x;
      } addr;
      
      int main(void) {
      //  printf("%d\n",(sizeof(char[x][21846])) >> 16);  // x/3
          
          printf ("%d",(&addr.x.bytes)[1] - addr.x.bytes);
          return 0;
      }
      
      bagor.c:20:30: error: invalid use of flexible array member
        printf ("%d",(&addr.x.bytes)[1] - addr.x.bytes);
                                    ^
      Ответить
    • Ура!
      Делит!

      https://ideone.com/sNzX8P

      #include <stdio.h>
      
      int main(void) {
      	char bytes22[22];
      	printf ("22 / 4 = %d\n",(int *)(&bytes22)[1] - (int *)bytes22);
      	char bytes45[45];
      	printf ("45 / 4 = %d\n",(int *)(&bytes45)[1] - (int *)bytes45);
      	
      	return 0;
      }
      Ответить
      • Сделай деление на 2, и в макрос запихни. И чтобы без минуса.

        Я сейчас пытаюсь по модулю 2 реализовать через структуру, [0...100]={{0,1}}, и каст с чар
        не получаеццо (((
        Ответить
        • Я могу сделать деление на любое натуральное число.
          И отрицательные тоже, лол.
          Ответить
    • Деление любых чисел.

      int div(b,a)
      {
          typedef struct {char lalk[a];} DIVISOR;
          char bytes[b];
          return (DIVISOR*)(&bytes)[1] - (DIVISOR*)bytes;
      }


      https://ideone.com/F5CPSJ

      Асемблерный выхлоп чист как слезинка лалки:
      div:
              movsx   rax, edi
              movsx   rsi, esi
              cqo
              idiv    rsi
              ret
      Ответить
      • Скилл.
        Я чото не могу распарить, пойду посплю.
        Ответить
        • >чото не могу распарить
          Упростил до невозможности ценой UB.
          div(a,n)
          {
              struct {char o[n];} *x=NULL, *y=a;
              return x-y;
          }
          When two pointers are subtracted, both must point to elements of the same array object or just one past the last element of the array object (C Standard, 6.5. 6 [ISO/IEC 9899:2011]); the result is the difference of the subscripts of the two array elements. Otherwise, the operation is undefined behavior.
          Ответить
          • Т. е. в сишке разность указателей — это не разность адресов, а разность индексов воображаемого массива, чтобы работала «арифметика указателей», поэтому и происходит деление (компилятор автоматически делит разность указателей на размер элемента массива)?
            Ответить
            • Да. Это же удобство высокоуровневого языка, чтобы инкремент срабатывал как итератор.

              Массив — это указатель (с оговорками).

              Инкремент указателя, увеличивает его значение на размер типа.

              Типичная ошибка начинающих:
              T *x = someArray();
              *x+=sizeof(T); //неверно
              *x++; //переход к следующему элементу
              По сути можно считать инкремент указателя «перегруженным» аки итератор в крестах.

              Edit: кстати там нужно было наоборот, return y-x; но всё-равно это UB-говнище )))
              Ответить
            • Так же, мало кто знает, но в Сишке разность указателей ещё и возвращает специальный тип ptrdiff_t, знаковую (!) версию size_t.

              https://en.cppreference.com/w/c/types/ptrdiff_t

              Там разложены забавные грабли:
              ptrdiff_t is used for pointer arithmetic and array indexing, if negative values are possible. Programs that use other types, such as int, may fail on, e.g. 64-bit systems when the index exceeds INT_MAX or if it relies on 32-bit modular arithmetic.

              Only pointers to elements of the same array (including the pointer one past the end of the array) may be subtracted from each other.

              If an array is so large (greater than PTRDIFF_MAX elements, but less than SIZE_MAX bytes), that the difference between two pointers may not be representable as ptrdiff_t, the result of subtracting two such pointers is undefined.

              For char arrays shorter than PTRDIFF_MAX, ptrdiff_t acts as the signed counterpart of size_t: it can store the size of the array of any type and is, on most platforms, synonymous with intptr_t).
              Ответить
              • приведи пример когда size_t не равен ptrdiff_t
                Ответить
                • Когда ptrdiff_t отрицательный.

                  ptrdiff_t — знаковый (т.к. разность).
                  size_t — беззнаковый (т.к. размер).

                  Потому PTRDIFF_MAX может быть меньше SIZE_MAX.
                  Из-за этого случаются забавные багры.
                  Ответить
                  • показать все, что скрытоvanished
                    Ответить
                    • Наставления TheCalligrapher о данном багре:
                      https://govnokod.ru/5026#comment65072
                      Ответить
                      • калиграфер еще больше тему развил
                        https://govnokod.ru/5026#comment65075

                        Действительно, массив не обязан иметь ничего общего с указателями, особенно если вспомнить сегментную модель
                        Ответить
                        • В сегментированной модели нельзя указатель кастить в инт и инт в указатель.

                          В реальном режиме вместо каста нужно применять формулу segment*16+offset. Обратно тоже можно, хотя обратное преобразование уже не будет однозначным (в смещение можно поместить от 4 битов до полного размера смещения).

                          В защищённом для получения линейного адреса нужно брать базу из таблицы дескрипторов: ldt[selector].base+offset (псевдокод). А вот обратного преобразования из линейного адреса в указатель уже может не быть. Если нет готового селектора с подходящей базой, его нужно создавать.

                          Не массив не имеет ничего общего с указателем, а линейный адрес. Разность указателей, преобразование линейного адреса в указатель становятся нетривиальными задачами.
                          Ответить
                          • Я ещё напомню, что сегментированные модели были двух типов: huge и «обычные».

                            В «обычных» размер массива был ограничен размером смещения (near ptr), например, 64K для 16-битного кода. Ну чтобы сегменты не переключать.

                            В huge размер массива не был ограничен. Кодогенератор высирал очень сложный код, который при итерации массиву отслеживал границы сегментов, чтобы в нужный момент переключить селектор.

                            intptr_t и uintptr_t в сегментной модели не имеют смысла. В сегментной модели длинные указатели по сути являются структурой из двух полей: сегмент(селектор) и смещение. Так что знаковость/беззнаковость нужно применять не к указателю, а к отдельным его полям.

                            Короткие указатели — да, числа. В моделях, кроме huge, максимальное значение короткого указателя совпадает с максимальным размером массива (минус один).

                            Где intptr_t и uintptr_t могут иметь смысл? В несегментных моделях, в которых по какой-то причине максимальный размер массива не совпадает с размером адресного пространства.
                            Ответить
                            • То есть в общем случае к указателю нужно относиться как к «чёрному ящику» и не путать его с линейным адресом.
                              Ответить
                • из самого маленького указателя (0) вычти самый большой (ULLONG_MAX) - что получится?
                  Ответить
                  • показать все, что скрытоvanished
                    Ответить
                    • UINTPTR_MAX
                      Ответить
                      • да, спасибо, макс размер массива не обязан быть равен размеру всей адресуемой памяти

                        Забавно, что мы как-то с Бормандом про это говорили, и я жаловался, что даже в 64х битной джаве или .net у меня размер массива 32х битный int
                        Ответить
                        • Кстати, а ведь на x86_64 указатели знаковые. Они по знаковым правилам работают. А в центре виртуальной памяти дырка которую нельзя замапать.
                          Ответить
                          • По идее я не должен ничего про это хотеть знать, но всё таки спрошу: а почему?
                            Ответить
                            • Все 64 бита мапать дорого, а юзать это пока никто не будет.

                              Поэтому там мапается какой-то небольшой кусок (на 52 бита что ли?). А остальные биты по знаковым правилам догоняются до 64. И получается положительный кусок для юзера и отрицательный кусок для ядра, а между ними дырка. Чтобы когда интел добавит больше битов в пейджтейблы твои указатели продолжили работать без изменений в коде.
                              Ответить
                              • показать все, что скрытоvanished
                                Ответить
                                • Ядерная память прижата не к середине виртуального адресного пространства, а к самому верху.

                                  | память юзера | ... дырка на будущее... | память ядра |
                                  Ответить
                                  • А что будет с реальными адресами по ту сторону от mmu?
                                    Там сверху будет оборудование, а снизу ram, и адрес ограничен макс объемом памяти cpu?
                                    Ответить
                                    • А к физическим адресам это не относится, насколько я помню. Там тоже не все биты доступны (48?). Но добивается нулями, т.е. всё внизу.
                                      Ответить
                                    • > снизу ram

                                      Да там ёбаная помойка из-за легаси же. Дырки под хуйню в первом мегабайте. Дырки под иса хуйню чуть выше. Дырки под apic и флешку в конце четвертого гига. Ну дальше вроде всё ровно.

                                      Интересно, сколько пирфоманса в кремнии теряется из-за этой совместимости.
                                      Ответить
                                      • еще была дырка в районе 16-го мегабайта, но отключалась в биосе еще в моем глубоком децтве *

                                        * http://lkml.iu.edu/hypermail/linux/kernel/0008.0/0465.html
                                        (но чел не прав, кмк, туда видяха мапилась)


                                        >, сколько пирфоманса в кремнии теряется из-за этой совместимости.

                                        Скока вообще всего теряется из за реального режма, сегментов, хардварного переключения тасок и прочей хуиты
                                        Ответить
                                        • > в районе 16 мегабайта

                                          Ну это и есть isa memory hole, не?
                                          Ответить
                                          • Мне казалось, что туда мапилась память старых видях (ну исашных, да)
                                            То есть не всех исов, а именно видях
                                            Ответить
                                            • Вроде никому, кроме видях, это не было нужно. Почти все устройства работали через порты. Накопители (жёсткие, сидюки) работали через DMA, т. е. могли срать по любому адресу основной памяти, окно не требовалось.
                                              Ответить
                                          • показать все, что скрытоvanished
                                            Ответить
              • > result of subtracting two such pointers is undefined

                А потом люди жалуются почему в жабе всё знаковое и массив на всю память не пильнуть...

                З.Ы. Кому вообще понадобилась отрицательная разность указателей? Вот реально, кто-то вычитает больший из меньшего?

                Сказали бы, что вычитать надо в правильном порядке, иначе 2s complement. Хотя это и сейчас можно через каст в uintptr_t перед вычитанием.
                Ответить
              • > в Сишке
                > cppreference
                Ответить
      • Только минус надо убрать. Не совсем честно.
        Ответить
        • В вычитании указателей вся суть. Хз как его убрать.

          Кстати код можно было записать и короче, убрав касты.
          div(a,n)
          {
              char d[a];
              struct {char o[n];} *x=(&d)[1], *y=d;
              return x-y;
          }
          Однако в этом случае появляются ворнинги.
          Ответить
      • Как у тебя массивы переменной длины на стеке скомпилились? О_о
        Ответить
    • https://twitter.com/hashtag/define
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • Хуйня, на плавучих питухах не сработает. И с отрицательными числами хуйня будет
      Ответить
      • Патамучто это плавающий питух, который априори говно. И чем вы быстрее это поймёте, чем будет лучше.
        Ответить
      • На отрицательных нормально всё: см. ассемблерный выхлоп и тесты на ideone.

        А разгадка проста:
        Читать далее ==>
        Ответить
        • > а разгадка проста

          Это UB и конпелятор вообще забил на этот кейс, просто idiv, который он писал для положительных, проканал?
          Ответить
          • https://godbolt.org/z/YaKK8P

            Интересно что он ставит также imul.

            Думаю со сложениями неправильно и не получится. Ведь в дополнительном коде операции со знаковыми и беззнаковыми по сути одинаковы.

            Потому когда оно неявно кастит unsigned size_t в int то результат эквивалентен.

            Вот в прямом и обратном коде это не сработает, но где же взять такую машину или хотя бы компилятор?

            Edit: Я бегло глянул на других архитектурах там тоже умножение знаковое.
            Ответить
            • > умножение знаковое

              Лол, т.е. сишники смеялись над жабой, что там знаковый размер массива. А на деле он и в сишке через знаковое умножение вычисляется?

              А вообще - попробуй беззнаковые инты на входе.
              Ответить
              • Проверил RISC V, MIPS, ARM. А также в шланге и штеуд-компилере.
                Везде умножение знаковое.

                Я уж думал из-за интов, написал ему явно:
                >unsigned mul(size_t x, size_t y) {

                Выхлоп не меняется.

                В MIPS кстати сложение беззнаковое addu $2,$4,$5

                Но, как я указал выше, для сложения побитовый результат, интерпретированный как signed будет верным.
                Ответить
            • Прямой код сейчас используется в плавпитухе (у него есть несколько инструкций для целых чисел: FIADD, FIMUL и т. п.). Но этот плавпитух для адресов не используется. Он использовался разве что для 64-битных чисел на 16- и 32-битных машинах, да и то редко (в «Турбо Паскале» был тип данных «Comp» как раз для этого питуха, сишка же для long long высирала сложный код с целочисленными инструкциями, разбивая операнды на половинки).
              Ответить
            • https://godbolt.org/z/Kcaenj
              int add(int x, int y) {
                  return &((void*)x)[y];
              }
              
              int mul(int x, int y) {
                  return sizeof (char[x][y]);
              }
              
              int change_sign(int x) {
                  return mul(x, -1);
              }
              
              int decrement(int x) {
                  return add(x, -1);
              }

              change_sign:
                      mov     eax, edi
                      neg     eax
                      ret
              decrement:
                      lea     eax, [rdi-1]
                      ret

              Впечатляет.
              Ответить
              • И даже через «деление» отрицание работает верно:

                https://godbolt.org/z/9n6MKc

                div(b,a)
                {
                    typedef struct {char lalk[a];} DIVISOR;
                    char bytes[b];
                    return (DIVISOR*)(&bytes)[1] - (DIVISOR*)bytes;
                }
                
                neg(a)
                {
                    return div(a,-1);
                }
                
                div:
                        movsx   rax, edi
                        movsx   rsi, esi
                        cqo
                        idiv    rsi
                        ret
                neg:
                        movsx   rax, edi
                        neg     rax
                        ret
                Ответить
                • Охуеть, конечно. Как конпелятор эти царизмы доказательно свёл к делению/умножению-то?..
                  Ответить
                  • На остатке я его таки немного обломал:
                    rem(a,n)
                    {
                        struct {char o[n];} *x=a,*y=0;
                        return a-sizeof(char[n][x-y]);
                    }
                    
                    rem:
                            movsx   rax, edi
                            movsx   rcx, esi
                            cqo
                            idiv    rcx
                            imul    eax, esi
                            sub     edi, eax
                            mov     eax, edi
                            ret
                    Ответить
                    • Кстати в арме похоже UB
                      rem:
                              mov     r0, #0
                              bx      lr


                      Я не могу понять почему такой выхлоп.
                      На остальных рахитектурах нормально. Например RISC V
                      rem:
                              div     a5,a0,a1
                              mulw    a1,a5,a1
                              subw    a0,a0,a1
                              ret
                      Ответить
                      • > Я не могу понять почему такой выхлоп.
                        Ты же сам писал:
                        >>> When two pointers are subtracted, both must point to elements of the same array object or just one past the last element of the array object (C Standard, 6.5. 6 [ISO/IEC 9899:2011]); the result is the difference of the subscripts of the two array elements. Otherwise, the operation is undefined behavior.
                        y здесь точно не является элементом того же массива, что и x, поэтому на любом входе это UB.
                        Ответить
                        • Там дело не этом.

                          Даже если сделать без UB (через массив), то ассемблерный выхлоп вообще не меняется.

                          На ARM64 он нормальный, а вот на ARMе какая-то питушня:

                          ARM
                          https://godbolt.org/z/qrfdEY
                          rem:
                                  mov     r0, #0
                                  bx      lr


                          ARM 64
                          https://godbolt.org/z/nnPGxE
                          rem:
                                  sxtw    x2, w0
                                  sxtw    x3, w1
                                  sdiv    x2, x2, x3
                                  msub    w0, w1, w2, w0 ; MSUB Rd, Rn, Rm, Ra. → Rd = Ra - Rn*Rm.
                                  ret
                          Ответить
                        • Оказалось дело не в левых указателях, просто нужно было не лениться и явно задавать типы на сигнатуре:
                          https://godbolt.org/z/cnKfG8
                          
                          int rem1(size_t a,size_t n)
                          {
                              struct {char o[n];} *x=a,*y=0;
                              return a-sizeof(char[n][x-y]);
                          }
                          Нетипизированное B-style распиздяйство до добра не доводит.
                          Ответить
            • Гуглим, где встречался обратный код. Он встречался в CDC 6600, в PDP-1, в LINC и в UNIVAC. Т. е. в технике 1960-х на дискретных транзисторах и с памятью на магнитных сердечниках (отсюда и «core dump»). Боюсь, что под такие процессоры нет готового бекенда ни для «gcc», ни для «clang», поэтому кросскомпилятор собирать не из чего.
              Ответить
        • Кстати, попробуй по приколу после этого кода ассёртнуть, что число неотрицательно. Конпелятор скорее всего закешировал утверждения a > 0 и b > 0. И теперь будет их юзать при оптимизации. Даже если число реально отрицательное. И выпилит любые проверки и ассёрты нахер.
          Ответить
    • #define max(x, y) sizeof(union{char X[x], Y[y];})
      Ответить
      • Гениально!
        Ответить
      • Спасибо.
        min(x, y){ return  -sizeof(union{char X[-x], Y[-y];}); }
        Ответить
      • Лучше вынести в отдельную функцию.

        На отрицательных компилятор ругается:
        prog.c:5:37: error: size of array ‘X’ is negative
        > #define max(x, y) sizeof(union{char X[x], Y[y];})

        Так же мне удалось найти баги:
        https://ideone.com/ukiT12
        max(int32_t x, int32_t y){ return sizeof(union{char X[x], Y[y];}); }
        
        	printf("%d\n",max(12,-12)); //-12
        	printf("%d\n",max(0,-1)); //-1
        	printf("%d\n",max(-1,0)); //-1


        Несмотря на явное указание int32_t оно похоже считает их беззнаковыми.
        Ответить
        • Для размеров массивов всегда используется один встроенный тип (size_t, кажется).

          Беда в том, что в сишке типизация слабая, и тут int32_t кастится в size_t даже без ворнингов.
          Ответить
      • clang 13.0.0 x86-64
         error: fields must have a constant size: 'variable length array in structure' extension will never be supported


        А ICC возвращает константу.
        https://godbolt.org/z/TEd47s6oW
        max:
                xor       eax, eax                                      #2.12
                ret                                                     #2.12
        
        min:
                xor       eax, eax                                      #5.12
                dec       eax                                           #5.12
                ret                                                     #5.12
        Ответить
        • А с констэкспрами можно что-нибудь сделать?
          Ответить
          • Проблема в том что clang, ICC и MSVC упираются в VLA внутри struct/union.

            А в С++ вообще нет никаких VLA.

            > констэкспрами можно что-нибудь сделать
            Думаю ими можно почти всё. Но тогда весь смысл хака исчезнет, подменившись шаблонюшней.
            Ответить
          • TCC тоже возвращает константу.
            mov    eax,0x8
             leave  
             ret

            При этом все компиляторы начинают работать правильно, если задать у массивов фиксированные значения.
            union{char X[10], Y[42];} b;

            Причём свёртывают (включая TCC) в компайл-тайме.

            То есть макрос будет хорошо работать только на заранее известных константах, которые можно вычислить в compile-time.
            Ответить
    • #define add(x, y) &((void*)x)[y];
      
      // MSVC не нравится void*. Заменил однобатовым char.
      // А TCC не компилил без каста в int.
      
      int add(int x, int y){ return (int) &((char*)x)[y]; }
      Ответить
      • int mul(int x, int y){ typedef char m[x]; return (int) &((m *)0)[y]; }
        Ответить
        • > typedef char m[x];
          Не понял. А зачем такие костыли с VLA?
          Можно же без него. См. начало треда.

          #define mul(x, y) (sizeof (char[x][y]))
          Ответить
      • int FMA(int x, int y, int z){ typedef char m[x]; return (int) &((m *)z)[y]; }


        FMA = fuzzed mul-add = x*y+z.
        Ответить
        • Ещё вариант FMA:
          int FMA(int x, int y, int z){ return (int) &((char *)sizeof(char[x][y]))[z]; }


          Или так:
          int FMA(int x, int y, int z){ return (int) &((char *)z)[sizeof(char[x][y])]; }
          Ответить
    • Если заменить минусы на ~ и добавить каст в unsigned, то и макрос MIN начинает нормально компилироваться во всех компиляторах *.
      #define MIN(x, y)~sizeof(union{char X[(unsigned)~x], Y[(unsigned)~y];});

      *везде кроме убогого MSVC
      error C2148: total size of array must not exceed 0x7fffffff bytesx86 msvc v19.0 (WINE) #1
      Ответить
      • А минус уже выразили через питушню? Та то можно было min(x, y) = sum(x, y) - max(x, y)
        Ответить
        • > А минус уже выразили через питушню?
          > можно было min(x, y) = sum(x, y) - max(x, y)

          Вот, пужулуйста
          #define min(x,y) &( &((char*)x)[y] )[-sizeof(union{char X[x], Y[y];})]

          Тоже неплохо.
          https://ideone.com/ywg924
          Ответить
        • Дампик:
          int min(int x, int y){return &(&((char*)x)[y])[-sizeof(union{char X[x],Y[y];})];}
          
          int min1(int x, int y){return ~sizeof(union{char X[~x],Y[~y];});}
          
          min:
                  movsx   rsi, esi
                  movsx   rdi, edi
                  cmp     rdi, rsi
                  lea     rax, [rdi+rsi]
                  cmovb   rdi, rsi
                  sub     rax, rdi
                  ret
          min1:
                  mov     eax, edi
                  not     esi
                  not     eax
                  cmp     esi, eax
                  cmovnb  eax, esi
                  not     eax
                  ret


          Кстати вариант с минусами считал 0 максимальным. А с побитовыми отрицанием такого бага нет.
          Ответить
    • Сишка в Гарвардской архитектуре возможна?

      Там же будут два типа указателей: на данные (вроде void *) и на код (вроде void(*)(void)). У этих указателей может не совпадать размер, если мощности пространства данных и пространства кода разные.

      Это не к этому коду, просто вопрос.
      Ответить
      • Ну в общем-то кастовать их друг в друга тебе никто и не разрешал (см. срач о dlsym в posix)... А в крестах ещё есть указатель на член класса, который физически не кастуется в обычные.
        Ответить
        • Это чёрный ящик, который ещё передаёт this, чтобы можно было вызывать виртуальные методы?
          Ответить
          • Не, this ты сам передашь по левую сторону стрелочки. Там оффсет для коррекции this перед вызовом, емнип. Ну и оффсет метода в vmt. Если я не гоню.
            Ответить
            • Кажется, понял. «Указатель на член» содержит не сам указатель, а смещение от начала vmt, а настоящий указатель получается после применения this. Так?
              Ответить
              • Так. Причём перед применением, возможно, this придётся скорректировать, чтобы указывало куда нужно (например в случае множественного наследования, если пытаемся добраться до члена класса, стоящего не первым в списке родителей)
                Ответить
                • в такую каку можно и без явной работы с указателем на члена наступить.

                  Был же такой прикол, когда у тебя есть Child, а ты его кастишь в void*, а потом реинтерпретером в Parent, и пихаешь в функцию, ожидающую Parent.

                  В жабке или C# было бы ничего стращного, но в крестах будет бадабум
                  Ответить
              • Ты наверное привык в высокоуровневному говну, где указатель на метод неявно захватывает и объект?

                в крестах так не принято, к счастью
                Ответить
      • К слову, ты и х86 можешь превратить в псевдо-гарвард с помощью сегментации. Не в long mode, конечно.
        Ответить
        • В long mode оставили два сегментных префикса: FS: и GS:.

          Так что даже в long mode не чистый flat, а смешанная модель.
          Ответить
          • Но там от них только оффсеты остались и вообще лежат в MSR а не в GDT...
            Ответить
            • Ой, там пару лет назад в связи с этими FS/GS была такая драма с эпичными баграми.

              Луникс иногда использовал FS для внутренних нужд. За это отвечал один бит в этом регистре.
              И установить его можно было только сискалом.

              Однако Штеуд внедрил инструкции для прямой записи в эти регистры.
              И это приводило к тому что можно было из юзерспейса поменять смысл FS, и повысить привилегии.

              Дело осложнилось SGX, который вроде называется Secure что-то, а на деле — решето.
              SGX выступил ещё одним вектором атаки.

              https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/best-practices/guidance-enabling-fsgsbase.html

              Но ситуацию спас сотрудник Макрософт (!) Саша Левин, который допилил для Linux необходимые ядру изменения.

              http://lkml.iu.edu/hypermail/linux/kernel/2008.0/02467.html

              Почитайте ссылки, там очень добротный контент.
              Ответить
              • Как всё сложно.

                Итак:
                1. В третьем кольце защиты нельзя сделать MOV GS, 42
                2. На это полагалось ядро Линукса.
                3. В Ivy Bridge появились четыре инструкции, позволяющие модифицировать FS и GS даже из третьего кольца.
                4. На эту возможность ядро Линукса не было рассчитано.
                5. Но эти действия можно запретить битом в CR4.

                Всё правильно понял, ничего не наврал?
                Ответить
                • Да. Хорошо суммировал.

                  Но упустил самое вкусное, на десерт:

                  > Sasha discovered that the SGX (sic!) offerings out there 
                  > ship rogue kernel modules enabling FSGSBASE behind the kernels back 
                  > which opens an instantanious unpriviledged root hole.


                  > The SGX-LKL project is designed to run existing unmodified Linux binaries inside of Intel SGX enclaves.

                  https://github.com/lsds/sgx-lkl/issues/528
                  Ответить
                  • сиречь ядро ядром, а модули всё равно насрут?
                    Ответить
                    • Модули линкуются в ядро, т. е. становятся его частью. Загруженный модуль неотличим от ядра.
                      Ответить
                      • а была же идея модули запускать на первом кальце, как и драйверы

                        во времена микроядер была такое мысль
                        Ответить
                        • Ничего не понимаю. Интел дал им четыре кольца защиты, а они используют не все. Это системные программисты? Это системные программисты?
                          Ответить
                          • Виртуалки используют. Или это -1 кольцо?
                            Ответить
                            • Кольца -1, -2, -3 — это уже не совсем кольца, это отдельные режимы работы. На них не распространяется IOPL и прочая питушня.
                              Ответить
                        • Пишут, в OS/2 ещё интереснее было: там кольцо 2 использовалось для юзермодного кода, которому позволено срать в железо.

                          А вот в ARM всё хуже. PL0 для юзермода, PL1 для ядра, PL2 для гипервизора. В ARMv8 добавили ещё один, аналог SMM. А вот промежуточных уровней у ARM нету.
                          Ответить
                  • SGX-LKL для приложения, запущенного в анклаве SGX, включает доступ к содержимому FS, GS, и оно может для себя получить рут?
                    Ответить
                    • Именно.

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

                      Особенно пиздец в этом всём, что технология со словом «Secure» в названии активно используется для повышения привилегий.

                      Вдвойне пиздецово, то что SGX позволяет скрывать чем занимается процесс и данные даже от администраторов. Что идеально для запуска и сокрытия вредоносного кода от сканеров.

                      Нашёл реальный пример, как на Винде были схожие проблемы

                      Intended to protect sensitive information from snooping, SGX allows applications to lock off areas of memory, dubbed enclaves, that cannot be accessed by the operating system nor other processes. The idea is that you run cryptographic or anti-piracy digital rights management code within an enclave so that it cannot be spied upon by even the administrators of the machine.

                      In the case of CVE-2018-18098, the technology potentially allows an attacker to game SGX to gain admin clearance. The problem lies not within the processor's SGX hardware, though, but in the software layer above it. When enclave code is installed by a normal user on a Windows system, it is possible to hijack the installer, via a process injection attack, to gain admin rights on the box.


                      А втройне пиздецово что уже так засрали своим «secure» говном, которое по сути anti-secure. Настолько всё усложнили, что очень трудно понять даже описание найденной дырки. А найти в коде и подавно.
                      Ответить
                      • Теперь вредоносный код может получить аппаратную защиту от антивирусов...

                        К слову, из Вики: «в процессорах Core 11 и 12 поколений поддержка технологии SGX удалена». Поняли, что обосрались. Но процессоры с этой дырой ещё долго будут в ходу.
                        Ответить
                        • > В процессорах Core 11 и 12 поколений поддержка технологии SGX удалена

                          А пропаганда как обычно представляет всё в другом свете:
                          «Теперь машины на базе этих чипов не смогут воспроизводить диски Blu-ray в разрешении 4K».

                          Пользователи скоро сами попросят вставить им Microsoft Pluton ректально.

                          > Теперь вредоносный код может получить аппаратную защиту от антивирусов...

                          Так точно.

                          Кстати не только у Штеуда есть анально огороженная параша для DRM.

                          У ARM с AMD тоже всё в порядке. В кернелы поновее и поддержку завезли (у меня в /dev пока такого говна нет)
                          https://www.kernel.org/doc/html/v5.9/staging/tee.html?highlight=platform%20security%2 0processor%20psp
                          A TEE (Trusted Execution Environment) is a trusted OS running in some secure environment, for example, TrustZone on ARM CPUs, or a separate secure co-processor etc. A TEE driver handles the details needed to communicate with the TEE.

                          The AMD-TEE driver handles the communication with AMD’s TEE environment. The TEE environment is provided by AMD Secure Processor.

                          The AMD Secure Processor (formerly called Platform Security Processor or PSP) is a dedicated processor that features ARM TrustZone technology, along with a software-based Trusted Execution Environment (TEE) designed to enable third-party Trusted Applications. This feature is currently enabled only for APUs.
                          Ответить
                          • У ARM и у AMD этот код отдельное ядро выполняет?
                            Ответить
                            • У AMD не просто отдельное ядро, а отдельный копроцессор со своей операционкой, ОЗУ и прочим.

                              Причём иронично что это копроцессор ARM. 32-bit Cortex-A5.
                              Ответить
                            • У ARM'ов "трастзона" -- это просто режим проца, ортогональный остальным. И в этом режиме по шине бегает бит secure, по которому железо понимает от кого запрос и может его заблочить.
                              Ответить
                              • >трастзона
                                Every time i see a news item about these trusted systems i can't help asking myself a few things :

                                - Why it isn't named "Don't trust the owner/user of this device" environment because that reflects what those things do.

                                - Where can i buy new devices without that environment ?
                                Ответить
                                • > trusted

                                  Обыватели не понимают смысл термина "trusted"...

                                  Он означает совсем не то, что код няшный и пушистый и ему можно доверять.

                                  Он означает код, которому ты вынужден доверять от безысходности. Потому что если этот код скопроментирован -- остальные части системы уже ничего не с этим сделать не смогут.

                                  Т.е. например ты вынужден доверять фирмвари, иначе ничего не загрузится.
                                  Ответить
                                  • > Он означает код, которому ты вынужден доверять

                                    Это маркетологический трюк расчитанный именно на то чтоб обыватель неправильно понял.

                                    Потому назвали «trusted», а не «анальный тюбик».
                                    Ответить
                                    • Как всегда маркетологи хороший термин извратили...
                                      Ответить
                                      • Если бы они это назвали «анальным тюбиком», у них был бы конфликт с секс-шопами. А по термину «trusted» ни с кем конфликтов нет.
                                        Ответить
                              • > У ARM'ов "трастзона" -- это просто режим проца, ортогональный остальным.

                                На x86 не так. Там вшиты отдельные копроцессоры со своей закрытой осью.

                                У Штеуда по последней информации 32 битный Quark под управлением... Minix.

                                Starting with ME 11, it is based on the Intel Quark x86-based 32-bit CPU and runs the MINIX 3 operating system. The ME state is stored in a partition of the SPI flash, using the Embedded Flash File System (EFFS). Previous versions were based on an ARC core, with the Management Engine running the ThreadX RTOS.

                                У АМД Cortex-A5 с непонятной прошивкой. Причём без него остальная часть проца работать не будет

                                > The PSP is an integral part of the boot process, without it the x86 cores would never be activated.

                                https://en.wikipedia.org/wiki/AMD_Platform_Security_Processor
                                Ответить
                                • Гуляла за городом Божья коровка,
                                  По веткам травинок карабкалась ловко,
                                  Глядела, как в небе плывут облака…
                                  И вдруг опустилась Большая Рука.
                                  И мирно гулявшую Божью коровку
                                  Засунула в спичечную коробку.
                                  Коровка ужасно сердилась сначала,
                                  Мычала и в стены коробки стучала…
                                  Но тщетно! Забыли о ней в коробке,
                                  Закрыли Коровку в шкафу, в пиджаке.
                                  Ах, как тосковала в коробке бедняжка!
                                  Ей снились лужайка, и клевер, и кашка…
                                  Неужто в неволе остаться навек?!
                                  Коровка решила готовить побег.

                                  Три дня и три ночи рвалась она к цели.
                                  И вот, наконец, вылезает из щели…
                                  Но где же деревья, цветы, облака?
                                  Коровка попала в карман пиджака.
                                  Однако она, не теряя надежды,
                                  Бежит на свободу из душной одежды:
                                  Там солнце, и ветер, и запахи трав…
                                  Но вместо свободы увидела шкаф!
                                  Тоскливо и страшно Божьей коровке.
                                  Опять она в тёмной пустынной коробке.
                                  Вдруг видит: вверху, где вставляется ключ,
                                  Сквозь щёлочку в шкаф пробивается луч!
                                  Скорее на волю! Коровка отважно,
                                  Зажмурясь, штурмует замочную скважину…
                                  И вновь оказалась в глухом коробке
                                  С огромною люстрой на потолке.
                                  Однако Коровка на редкость упряма:
                                  Нашла, где неплотно захлопнута рама…
                                  И вот вылезает она из окна —
                                  Ура! Наконец на свободе она!

                                  И вновь на знакомой лужайке букашка.
                                  Под нею, как прежде, колышется кашка,
                                  Над нею плывут в вышине облака…
                                  Но смотрит на мир осторожно Коровка:
                                  А вдруг это тоже Большая коробка,
                                  Где солнце и небо внутри коробка?!
                                  Ответить
                          • > не смогут воспроизводить 4х

                            Да ну? Я сварщица не настоящая, но разве недостаточно будет TPM, Secure Boot и гипервизора? Которые, внезапно, и требуются для win 11.

                            Ну да, ещё придётся вайтлистить вендоров прошивок, чтобы не забывали Boot Guard включить. Но я думаю это решаемо для майкрософт.
                            Ответить
                          • > Pluton

                            Вообще, забавно, что M$ повёлся на байки интела о "секьюрности" анклавов и вбухал в это кучу ресурсов. А на деле они оказались решетом.

                            И теперь они пилят всё сами.
                            Ответить
              • К слову, Винда тоже использует эти регистры.

                32-битная использует FS, а 64-битная — GS (не знаю, зачем они сменили регистр) для указания на TIB — thread information block — структурку, хранящую внутренние переменные ОС, относящиеся к текущему треду.

                Кстати, textsynth в одном примере, увидев [_tib], нагенерировал код для получения переменных TIB. Он даже это знает.
                Ответить
                • > структурку, хранящую внутренние переменные ОС, относящиеся к текущему треду

                  Ну так и GCC использует их для адреса thread localов.

                  > 32-битная использует FS, а 64-битная — GS
                  А не наоборот? В Линуксовом ABI наоборот.
                  i386 — GS
                  x64 — FS
                  Ответить
                  • Винда 32-битная точно использовала FS для своих нужд, а регистр GS приложение могло использовать свободно.
                    Ответить
                • > 32-битная использует FS, а 64-битная — GS

                  В gcc кстати есть флаг чтобы это отключить.
                  Но тогда будет перепитух с thread base pointer.
                  -mtls-direct-seg-refs
                  -mno-tls-direct-seg-refs
                  
                      Controls whether TLS variables may be accessed with offsets from the TLS 
                  segment register (%gs for 32-bit, %fs for 64-bit), 
                  or whether the thread base pointer must be added. 
                  Whether or not this is valid depends on the operating system, 
                  and whether it maps the segment to cover the entire TLS area.
                  
                      For systems that use the GNU C Library, the default is on.
                  
                  https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
                  Ответить
            • Сегменты вообще остались только ради того, чтобы ядреный код отличаться от пользовательского вроде.

              А жаль. Классная же была идея: выделаешь кусочек памяти, и реально железо тебе его защищает.
              Ответить
              • Вместо этого в Штеуде сделали тормозную, громоздкую и в общем нинужную систему с 5ю уровнями страничной адресации.

                Мечтай в одну руку, сри в другую.
                Ответить
                • При виртуализации двадцатью пятью...
                  Ответить
                  • У меня в реальном режиме ничего из этого нет.
                    Ответить
                    • И мегабайт памяти.
                      Ответить
                      • это физическое ограничение на количество дорожек же, совместимость с ним вернее

                        Что мешало сделать реальный режим без нахлеста?
                        Ответить
                        • Плевок в вечность. Указатели по 32 бита, а из-за нахлёста используются только 20.
                          Ответить
                        • > реальный режим без нахлёста

                          Гранулярность большая получится, что пиздец неудобно. Нахлёст был компромиссом между экономией памяти и достаточно лёгкой арифметикой указателей: если аллокатор минимизирует оффсет (а нахлёст даёт ему такую свободу), то в 99% случаев очень тяжёлую операцию по инкременту сегмента можно выкинуть и апдейтить только смещение.
                          Ответить
                        • Т.е. если с нахлёстом у тебя просто mov ax, [ds:si+bx] и аллокатор сваливает большую часть адреса в сегмент, то без нахлёста у тебя джва стула:

                          - хитровыебанный аллокатор, который никогда не пересекает 64к границы и из-за этого проёбывает память
                          - push si; push ds; add si, bx; mov ax, ds; adc ax, 0; mov ds, ax; mov ax, [ds:si]; pop ds; pop si на каждом обращении к памяти.
                          Ответить
                          • ты говоришь о макс размере сегмента в 64K, и это проблема (либо у тебя size_t такой либо ты пирдолишься как ты и показал, собссно универсальные поинтеры в BC так и делали вроде)

                            но я говорил о проблеме A20, из за которой у нас мегабайт. Если бы у нас было 2^16 сегментов, то было бы у нас и 4 гига памяти, не?

                            С гранулёмой можно было бы бороться через huge segments (сравни huge pages), алеж тогда пришлось бы делать description tables (иначе как узнать размер сегмента?) и был бы уже не честный реальный режим
                            Ответить
                            • > макс размере сегмента

                              Ну а нахуй это все надо, если у тебя регистры 32-битные? Реалмод такой странный именно из-за 16-битности.

                              Собственно поэтому на arm'овских контроллерах нет такой ёбли. Там 32-битный flat, хоть памяти и меньше, чем у древних х86.
                              Ответить
                              • твоя правда

                                если зашиться на то, что размер сегмента всегда 4гига, то и похуй.

                                Конечно, макс размер массива 4 гига кому-то может показаться гомосячеством при наличии 256 гигов оперативки в сервере например, ну так жабаёбы же живут например
                                Ответить
                      • Кстати, есть «unreal mode», который серьёзным софтом не используется, потому что несовместим с EMM, с VDM и с прочей питушнёй, работающей в V86.

                        Это делается так:
                        1. Переключаешься в защищённый.
                        2. Ставишь лимит у всех селекторов по четыре гига.
                        3. Возвращаешься в реальный.

                        Теперь ты можешь адресовать четыре гига, используя 32-битные смещения (с помощью префикса ADRSIZE).
                        Ответить
                        • А вот ещё причина, по которой нереальный режим не использовали: обработчики прерываний BIOS не сохраняли старшие 16 битов регистра EIP. Если код поместить выше первого мегабайта, то после очередного прерывания будет багор.

                          Нужно или все обработчики прерываний переписывать под себя, или ограничивать код первым мегабайтом.
                          Ответить
                          • А я ведь не знаю, как это исправить. Если в реальном режиме на IRQ приходит сигнал, то вызывается INT для 16-битного кода, который сохраняет только младшие 16 битов EIP. Старшие биты обработчик прерывания не знает, он их не сможет восстановить.

                            Остаётся только включать CLI для кода, расположенного выше первого мегабайта. Но это ужас.
                            Ответить
                            • сохранять стейт должен проц

                              знаешь же как работало хардварное переключение конь текста?
                              Ответить
                              • Насколько я понял, хардварное сохранение конь-текста по прерыванию возможно только в защищённом режиме.
                                Ответить
                            • Пффффь. Нужно просто писать программы меньше мегабата. Тем более в те времена это было легко, никакихифреймворком с поездом зависимостей.
                              Ответить
                              • Тем не менее, «Doom» и «Duke Nukem» для реального режима не осилили. Их сразу писали под защищённый.
                                Ответить
                        • > не используется

                          Потому что он бессмысленный... Раз у тебя регистры 32-битные, твой конпелятор к этому готов и тебе явно плевать на совместимость, то что мешает просто остаться в защищённом?

                          Прерывания можно обратно в реалмод зафорвардить если сам не хочешь обрабатывать.
                          Ответить
                          • Сложнааа. Нихуя не понятнааа. Не хочу защищённый.
                            Ответить
                            • Да во flat'е то чего непонятного? Даже проще, чем реалмод...

                              Ну хотя да, IDT чуть сложнее.
                              Ответить
                              • ну нихуя себе "чуть". У меня вообще вся картина мира рухнула, когда я узнал про защищенный режим, и про то, что адрес вовсе не адрес, а индекс в таблице какого-то говна
                                Ответить
                                • Между прочим, у меня в контроллерах этой хуйни нет.
                                  Ответить
                                  • бывают ли конктроллеры с x86?
                                    Ответить
                                    • Какой-то говнокод про промышленную железку на основе 286 тут постили...

                                      Другой вопрос, считать ли это контроллером.
                                      Ответить
                                      • в 286 уже можно флет, уже есть защищенка, страниц только нет
                                        Ответить
                                        • Флет с 16-битными смещениями?
                                          Ответить
                                          • кажется, я напиздел. Флета там не будет, но так как есть GDT/LDT, то вероятно можно указать размер сегмента, и хотябы сделать его не 64K.

                                            Впрочем, надо проверять.

                                            хатя...

                                            The segment address inside the descriptor table entry has a length of 24 bits so every byte of the physical memory can be defined as bound of the segment. The limit value inside the descriptor table entry has a length of 16 bits so segment length can be between 1 byte and 2^16 byte. The calculated linear address equals the physical memory address.

                                            говно какое. Как же всякие миниксы, OS/2 и прочие xenix Работали?
                                            Ответить
                                            • Создавали дохуя сегментов.

                                              В Windows 3.x была такая же проблема.

                                              Либо ограничиваешь массив 64 килобайтами, либо городишь костыли для переключения сегментов.
                                              Ответить
                                              • Вот забавно.

                                                В 1979-м году Intel хотел как лучше: отдельный сегмент для кода, отдельный для данных, нельзя случайно "выполнить данные", всё логично, удобно, и правильно.

                                                И уже через пять лет буквально начались анальные костыли ради массива более 64K
                                                Ответить
                                                • В 286 можно было адресовать память командами типа MOV AX, DS:[BX]

                                                  От начата DS: ты мог отступить максимум на 64 кило. А дальше нужно либо подкручивать базу селектора, либо создавать новый селектор с базой повыше.

                                                  Адресации scale-index-base, как на 386, где индекс можно умножать на scale, тогда ещё не было.
                                                  Ответить
                                            • Никак? Линус вон тоже только под 386 стал писать, когда эти ограничения сняли.
                                              Ответить
                                              • ну как жыж никак, если они работали?

                                                Линус изучал MMU, и решил сделать OS для PC со страницами (в 286 не было страниц, хотя и были защищенные сегменты), а миниксы работали и до этого

                                                https://vetusware.com/download/Minix%20for%20286%202.0.4/?id=9903
                                                Ответить
                                    • Прикинь, что в продаже бывает:

                                      https://www.chipdip.ru/product0/8008545452

                                      Клон 8086 в корпусе DIP40.

                                      Слабо под него плату развести?
                                      Ответить
                                    • > бывают ли конктроллеры с x86?

                                      В айфонах baseband processor на x86 -> https://lcq2.github.io/x86_iphone/
                                      Ответить
                                      • Потрясаяющая история:) А как же такой опотный реверсчик не признал интелоговно? Как можно было подозревать шифрование с сохранением уровня энтропии, воу?
                                        Ответить
                                      • А, еще есть "Intel Management Engine"
                                        https://ru.wikipedia.org/wiki/Intel_Management_Engine

                                        > Starting with ME 11, it is based on the Intel Quark x86-based 32-bit CPU and runs the MINIX 3 operating system.

                                        Т.е. там отдельный 32-битный x86-совместимый процессор под это говно выделен
                                        Ответить
                                        • >minix
                                          блядь) зачем? зачем?

                                          IME это вроде та хрень, через котору Йоханна Рутковска (тян хакер существует не только в аниме!) поломала интел>?

                                          а еще из за IME сервера вроде по десять минут грузятся
                                          Ответить
                                          • Отвечает балабоба:

                                            Есть ли у Йоханны Рутковски хуй? Есть. Есть хоть и со знанием средневекового этнографического языка. Она живет с дочерью и фантастическими партнерами на Соловках. Она смотрит свои лучи в массивных рашифровках викинго�йвоградского сонара, чтобы оправдать величавую книжку. В последние годы Йоханна напрямую убеждала мира руководить войсками души, делая их более смелыми.

                                            Рецензенты разного рода могут быть на то ли бессовестными или неприличными. Одна любимая хитросплетение математической школы стилистики в нашей реальности в основном предлагается именно британским писателям, самим себе часто удобно предпочитаемые альтернативы отчасти утешительны, но многим это исполнение воздуха не нравится.
                                            Ответить
                                            • да нет, в отличие от любимых всеми вами трапов, она настоящая
                                              Ответить
                                      • А ведь у других смартфонов у момеда тоже собственная прошивка. Какие у них процессоры используются?
                                        Ответить
                                        • в курьерах был 186 (что и позволило писать прошивку русским хакерам) но он не для ЦАПа был
                                          Ответить
                                          • Он был для парсинга hayes-команд?
                                            Ответить
                                            • Ну там много сложных протоколов было: для сжатия, для выбора частоты несущей (в этом месте прошивки хакали обычно), всякие функции АОН, вот это всё.
                                              Ответить
                                • Ну один раз попердолишься, настроишь.

                                  А потом то flat намного проще, чем реалмодные грабли. Да и работает обычно быстрее.
                                  Ответить
                                  • Плоское всегда проще "фигурного выпиливания", это касается и памяти, и доступа к диску (LBA), тут я не спорю.

                                    Но real mode у тебя из коробки, а для flat нужно чото там в CR* регистры загружать, *DT всякие.
                                    Ответить
                                    • > загружать

                                      Десять инструкций буквально... Ну и таблички, да.

                                      В лонг вот сложнее из-за пейджинга.
                                      Ответить
                                      • Когнитивное искажение такое есть: когда ты уже один раз что-то сделал, тебе кажется, что это легко и очевидно.
                                        Ответить
                                    • Основная жопа в том, что все сервисы bios/dos отвалятся. И ходить за ними уже не 10 инструкций.
                                      Ответить
                                      • А для этого лепят DPMI.

                                        Это по сложности почти как свой cygwin написать или ещё какую-нибудь прослойку.
                                        Ответить
                                        • Ну попроще, наверное, тогда не так уж много сисколлов было.
                                          Ответить
                                          • Можешь погуглить спецификации DPMI v. 0.9 и DPMI v.1.0.

                                            Нужно реализовать:
                                            1. Несколько функций INT 31h (не так много).
                                            2. Переходники для прерываний DOS и BIOS.

                                            И вот с реализацией переходников проблема, когда передаёшь данные не по значению, а по указателю. Нужно держать буфер в «реалмодной» памяти, чтобы DOS/BIOS его увидел.
                                            Ответить
                                            • может проще сразу в 32 перекключится и EFI вместо биосов?
                                              Ответить
                                              • Можно. И отказаться от DOS и реализовать доступ к файлам самостоятельно.

                                                Получишь... свой Линукс.
                                                Ответить
                                                • В EFI нету рази API для достипа к файлам?

                                                  Как же оно petuzh.efi грузит?
                                                  Ответить
                                                  • И есть и нету. FAT32 он обязан поддержать, остальное -- по желанию.
                                                    Ответить
                                                    • ну так дос, знаете ли, тоже нихуя не поддерживает кроме fat 16 (и fat32 если это dos 7.0), для остальтного нужно ставить драйвер
                                                      Ответить
                                            • Самое смешное -- когда 32-битный загрузчик и 32-битный CSM косплеят своих предков и общаются через реалмод.
                                              Ответить
                                              • Потому что глупый админ не догадался включить чистый EFI, когда ставил OS? (и наверное диск еще нужно в GPT, или не нужно?)
                                                Ответить
                                                • > или не нужно

                                                  Х.з., от настроения прошивки зависит. Флешки без GPT они вполне так грузят.

                                                  Но зачем в 2021 пердолиться с MBR?
                                                  Ответить
                                                  • Сейчас 2022.

                                                    Да не зачем, но я переодически вижу питузов, которые ставят на современный (вот почти уровня адлер лейк) комп винду без уефи. хуй знает зачем
                                                    Ответить
                                                    • Привыкли к заклинаниям из прошлого. В общем-то на пирфомансе это не сказывается.
                                                      Ответить
                                                      • «Русификация Линукса по инструкции 1996 года».
                                                        Ответить
                                                    • Интересно, а с nvme тоже можно бутнуться через csm? Или уже всё?
                                                      Ответить
                                                      • https://www.intel.com/content/dam/support/us/en/documents/memory-and-storage/enthusiast-ssds/PCIe-NVMe-SSD-Install-Boot-Guide.pdf

                                                        2.1.2
                                                        не
                                                        нельзя

                                                        у интела так точно
                                                        Ответить
                                      • Кстати, рекомендую:

                                        https://www.japheth.de/HX.html
                                        Ответить
                      • Мегабат
                        Ответить
      • А на cortex m0 гарвард с общим адресным пространством (из оперативки код не исполнить, хоть каст и сработает).
        Ответить
        • Хм, пишут что у других армов тоже гарвард, просто потом на уровне мультиплексоров ему дают читать оперативку через шину для кода.

          Тогда и х86 не чистый фон-нейман, если посмотреть на раздельный кеш данных и инструкций.

          Походу это разделение уже устарело.
          Ответить
          • Для армов есть специальная хуйня для обновления кэша инструкций, если в исполняемую память писать.
            https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/caches-and-self-modifying-code
            Ответить
            • Ну я о том, что труъ фон-нейманов больше нет. Похоже что их забросили сразу в момент изобретения пайплайна и спекуляции.

              И физически все ядра сейчас работают по-гарвардски, просто иногда добавляют роутинг с шины кода до оперативки.

              Или есть реальный пример выжившего фон-неймана?
              Ответить
          • У x86 есть ещё одно пространство: порты ввода-вывода, для которых отдельные инструкции. Без MMIO они бы вообще никак с основным адресным пространством не пересекались бы.
            Ответить
            • Но, как увидели, во многих примерах вы видите, что инструкция по входу в манипулирует значением флага: %ecx -> %eax (1, 2), а потом %eax вводит в регистр %ecx (4, 5), причём не просто %ecx отражается, а именно значением %eax (6). Если посмотреть файл <asm/desc.h> то видите там, как это сделано:
              #define SET_ZF(ZF) \
                      mov ecx, _ZF \
                      and ecx, _CSZ
                    #define SET_SF(SF) \
                      mov ecx, _CSZ \
                      and ecx, _SF
              
                    #define GET_ZF(ZF) \
                          or ecx, _ZF \
                      xor ecx, _CSZ
                    #define GET_SF(SF) \
                      or ecx, _SF \
                      xor ecx, _CSZ
                    #define GET_OF(OF) \
                      or _OF, _OCS

              Таким образом они не работают как установились. Но всё же постоянно выполняются.
              Ответить
          • По твоей логике даже если я отключу кеш, но врублю W^X, то получу Гарвард?
            Ответить
            • Если посмотреть на ядро -- одна шина юзается для чтения кода, а вторая для данных. Что похоже на гарвард.

              А дальше за L1 кешами всё это смешивается в кучу и уже становится похоже на фон-неймана. Плюс интел ещё когерентность между этими кешами поддерживает, чтобы усилить иллюзию (ARM -- нет).

              Хер знает, короче. Устарела вся эта классификация. Чуваки всё-таки про свои конкретные изобретения рассуждали, а не про то что через десятки лет наворотят.
              Ответить
              • Мне кажется, что плясать надо от того, что процессор показывает программисту.

                в 86 у тебя два адресных пространства: ненунжное(IO) и обычное(MEM).

                MEM на код и данные не разделяется, так что это как-бы гарвард.

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

                >Устарела
                Ну да, наверное это как с CISC/RISC, сейчас уже сложно сказать.

                зы: dram controller нам том же die, что и ядро, так что физически снаружи проца никакой разницы между кодом и даннымитоже нет: дорожки тянутся к dram
                Ответить
                • Как это IO ненужное? А как я буду хрюкать писиспикером? А как я буду срать в ком-порт?
                  Ответить
                  • Через USB.
                    Ответить
                    • зачем кстати IO поменяли на MMIO? не лучшель было расширить IO в 32 битном режиме?

                      не было бы глупых проблем типа "win32 не видит 4 гига памети"
                      Ответить
                      • А хуй знает, принципиальных отличий вроде нет, просто ещё один адресный бит...

                        Но возможно I/O инструкции чем-то плохи и тормозят, а поменять их уже нельзя. Как минимум там всё плохо с режимами адресации.
                        Ответить
                      • > винда не видит 4 гига

                        Самое смешное, что уже в 95 году х86 умел в PAE. Так что проблема тут далеко не в проце. Прыщи, к примеру, видели.
                        Ответить
                        • в w2k включили PAE, и сразу половина драйверов отвалилась. Пришлось запрещать ее по умолчанию, и вроде бы ее разрешено только в серверах (там драйвера обычно чуууть менее хуевые)
                          Ответить
                          • Ну вот да, проблема в анскилльных лалках, которые кастовали физический адрес в инт...
                            Ответить
                            • На 32-битных машинах было прикольно:
                              1. far-указатели были 48-битными (16 бит селектора + 32 бита смещения).
                              2. Линейные адреса были 36-битными (с учётом PAE).
                              Ответить
                      • Интересно, где в 95 году реально стояло 4 гига памяти? Какие-нибудь станции для рендера фильмов?

                        Не просто ведь на будущее интел эту фичу пилил.
                        Ответить
                        • Помню, в газете писали про суперкомпьютер Гидрометеоцентра. У него ещё дисковой памяти было гигов 60 — нереально много по тем временам.
                          Ответить
                        • на x86-то? и на win95? сомневаюсь чото)

                          рендерили поди на SGI каких нить
                          Ответить
                          • Да, полагаю, что суперкомпьютеры были не на x86. На x86 были заделы на будущее.
                            Ответить
                            • Далёкое будущее, которое на винде так и не настало...

                              А потом пришёл АМД и всё перевернул.

                              З.Ы. Блин, так то до сих пор продаются говноуты с 2 гигами.
                              Ответить
                              • Даже Windows 10 32-битная существует.
                                Ответить
                              • Кстати, в те героические времена, вероятно, благодаря свопу можно было сделать гигантский объём виртуальной памяти. Но с тормозными винчестерами той эпохи это была не работа, а пытка.
                                Ответить
                              • > Далёкое будущее, которое на винде так и не настало...


                                Да нет, на серверах таки настало. Я вживую видел 2003-й с PAE.
                                Ответить
                            • When you need the perfect 2GB laptop to play your favorite games...

                              Как бы намекает нам сайт HP.
                              Ответить
                              • Я держал в руках нетбук HP с двумя гигами. Для Windows 7 этого маловато. А более древнюю систему не поставишь, потому что в прошивку не включили мумулятор IDE. Нужно пердолиться с включением драйвера AHCI в инсталятор.

                                Такой perfect...
                                Ответить
                                • Ну favorite games from '90s вполне пойдут. Может быть даже из 2к0.
                                  Ответить
                                  • Ой не факт. Не только в оперативке дело жи. У меня GTA SA когда-то на гигабайте роботала. А тртья на джвух лагала)
                                    Ответить
                                • >Нужно пердолиться с включением драйвера AHCI в инсталятор.

                                  Это тн "F6 driver". При установке XP жмешь F6, и суаваеш дискету.

                                  Никогда не видел, чтоб AHCI нельзя было переключить в IDE

                                  Ваще 32битная семерка станет на 2 гига, но работать на нем всё равно хуёво
                                  Ответить
                                  • Ну это ноуты, у них уже чаще и чаще встречаются прошивки без легаси. Там и CSM запросто может не быть.
                                    Ответить
                                • Будь здоров!
                                  Ответить
                              • От PHP до HP одна буква. А в первом вообще лимит 128мб обычно ставят. Задумайся.
                                Ответить
                  • Хрюшка говорит: "XPIO".
                    Кошечка говорит: "MMIO"
                    Ответить
                • > программисту

                  Ядерному или прикладному? Прикладному то по-дефолту сейчас никто не даёт код патчить...

                  А адресное пространство вон у arm cortex m0 тоже общее (решили не экономить на спичках). Тем не менее, роутинга от шины кода до оперативки у него нет и указатели на данные в оперативке не пашут как указатели на код. Т.е. это почти труъ гарвард (был бы труъ, если бы флешка с кодом не читалась с шины данных).
                  Ответить
                  • любому.

                    а прикладник не может пометить страницу как W, насрать туда, и потом пометить X?

                    как же жыты работают? через трап-лины?
                    Ответить
                    • Может. Но по-умолчанию то это не так. А на винде под HVCI гипервизор не даёт ядру создать ring 0 страничку с X.

                      Какой фон-нейман )))
                      Ответить
                      • Сначала ты пишешь дырявую как говно ОС, где половина кода работает от Local System, а хеши паролей хранятся в памяти у процесса, которого можно дебагнуть, а потом начинаешь судорожно лечить всё это через железо, посредством виртуализации.
                        Ответить
                        • ps: впрочем, сама идея секур бута не кажется мне дурной. Просто лечат реально не то, через что их все ломают
                          Ответить
                          • > Просто лечат реально не то, через что их все ломают

                            Если посмотреть на развитие их конпелятора, то они последние годы реально лечат именно то, через что их ломают.

                            Просто они пошли немного по другому пути -- убить RCE как класс, даже если код написан бухим долбоёбом и спроектирован по наивным канонам 80-х.
                            Ответить
                            • Хотя от log4j все эти опции не спасут, конечно.
                              Ответить
                            • Ты имеешь ввиду, что они выпиливают всякие несекурные функции и пытаются как-то защищать память?

                              Просто долбоёб часто сам все портит при наличии specially crafted packet, как мы знаем, а хакер всё равно гаджет найдет.

                              Тут вся TCB, вся в система сгнила, всё менять надо.
                              Ответить
                              • > а хакер всё равно гаджет найдет

                                При работающих CFG и CET ему не особо приятно будет это делать... По сути, прыгнуть можно только в начало функции. А вернуться только туда, откуда функцию вызвали.

                                Но CET слишком сложный, конечно. Боюсь, что там тоже какие-нибудь баги найдутся и интел его отправит на кладбище не взлетевших технологий.
                                Ответить
                                • Ох бля. CET это когда стек дублируют, и проверяют, что там не засрали ретурн адрес?
                                  Ответить
                                  • Да, можно уже было тупо джва стека сделать...
                                    Ответить
                                    • Один для разрврата, другой для локальных пельменных, и запертить коду писать в первый. Только CALL и RET, и всё.

                                      А как же автоуничтежние локального фрейма при выходе из функици?
                                      Ответить
                                      • push rbp
                                        mov rbp, rsp
                                        ...
                                        mov rsp, rbp
                                        pop rbp
                                        Ответить
                                      • >А как же автоуничтежние локального фрейма при выходе из функици?

                                        Придётся во втором стеке городить контроль за фрейм-поинтером.
                                        Ну классическое:
                                        push ebp
                                        mov ebp, esp
                                        Ответить
                                      • > автоуничтежние локального фрейма при выходе из функици

                                        Шта? Ты про ret с циферкой, который в паскалевском конвеншене юзался? Я другой "автоматики", завязанной на ret не припомню. Всю жизнь вручную вилкой чистили через mov bp, sp или add esp, 42.
                                        Ответить
                                        • Я про то, что для правильного выхода из функции нужно, чтобы на верхушке стека лежал адрес разврата, не?

                                          То есть полюбасу придется подвинуть указатель на стек, либо как-то явно из него всё повыкидывать.

                                          про FramePointer там ужо выше все написали, но он же опционален

                                          Соглашусь, впрочем, что слово "автоматический" тут плохо подходит, потому что "ret" в случайном месте приведет к прыгу в локальную переменную
                                          Ответить
                                          • > про FramePointer там ужо выше все написали, но он же опционален

                                            Если фреймпоинтера нет, стек сначала очищают вручную с помощью add esp, 42 и pop'ов сохранённых туда регистров. Если включен стек протектор, после этого проверяется канарейка. И только после этого происходит ret. Да, в этот момент под rsp уже как раз адрес возврата.

                                            Если мы уберём адрес возврата на другой стек... то все остальные механики, описанные выше, ничего не заметят. Вообще ничего. Потому что при нормальной работе кода всё сбалансировано.

                                            > "ret" в случайном месте

                                            Ну откуда он там взялся? Какая-нибудь бага конпелятора, который забыл высрать эпилог функции?
                                            Ответить
                                            • Если я не сделаю pop или add esp, 42, то я не смогу сделать ret в нормальное место.

                                              Если мы унесем адрес возврата в другой стек, то я смогу сделать "ret" не сделав ни add esp, 42, ни pop.

                                              Таким образом вызвавшая меня функция может получить стек с моими переменными
                                              Ответить
                                              • > я смогу сделать "ret" не сделав ни add esp, 42, ни pop

                                                Это бага конпелятора имеется в виду? Или нарушение DEP? Мимопролетающая космическая частица, превратившая mov в ret? Или ты сам на асме такую хуйню написал?

                                                Я не понимаю суть проблемы, честно.
                                                Ответить
                                                • Бага компилятора, или криворукость асм программиста.

                                                  не, ну можно конечно перенести это на вызывающую сторону: пусть запоминает SP, а после вызова возвращает на место, такую call convention можно принять
                                                  Ответить
                                                  • >суть проблемы,
                                                    Сейчас нельзя случайно забыть вернуть SP на место, и спокойно ретнуться. А так станет можно.

                                                    Но может быть проблемы и нет, нужно попробовать, чтобы сказать. Сама идея хранить RET и переменные в разных местах, чтобы писанием в массив на стеке не засрать RET, наверное правильная идея
                                                    Ответить
                                                • Если стек один, мы ОБЯЗАНЫ удалять локальные переменные функции перед выходом.

                                                  Если для адресов развратов сделать отдельный стек, то мы сможем не удалять локальные переменные и вернуть их вызывающему коду.
                                                  Ответить
                                                  • > то мы сможем не удалять локальные переменные и вернуть их вызывающему коду

                                                    Привет, forth.
                                                    Ответить
                                                    • Кстати, на ARM несколько стеков будут выглядеть естественно:

                                                      1. «Стековые» инструкции не обязаны использовать R13=SP, они могут использовать любой регистр.

                                                      2. BL не использует стек, она лишь сохраняет адрес разврата в R14=LR. Вызываемая подпрограмма должна его где-нибудь пересохранить перед вызовами других подпрограмм из себя.
                                                      Ответить
                                                    • На самом деле в форте стек данных и стек локалок разные вещи. Последний может быть сделан на стеке развратов (например SP-FORTH), как в обычном конпеляторе. А может и отдельно
                                                      Ответить
                                                      • Хотя, если конпелять в стекувую машинку, можно просто вместо локалок стек данных вращать.
                                                        Ответить
                                                      • А в Постскрипте четыре стека: стек операндов, стек развратов, стек словарей и стек графики.
                                                        Ответить
                                                        • Не хватает только стека стеков, чтобы можно было стеки пихать в стек.
                                                          Ответить
                                                          • Кстати, сам словарь в форте, грубо говоря. тоже можно считать стеком, только попать стандартными средствами из него нельзя. Очередь поиска тоже можно считать стеком. В него можно пушать и попать словами, ALSO и PREVIOUS. Получается очередь поиска можно назвать стеком стеков.
                                                            Ответить
                                                        • 1. Стек данных
                                                          2. Стек развратов
                                                          3. Стек потока управления (для компиляции управляющих слов, может быть совмещён со стеком данных)
                                                          4. Очередь поиска
                                                          5. Стек локалок
                                                          6. Область данных фактически тоже стек, ALLOT может двигать указатель в обе стороны.
                                                          Ответить
                                                  • Спасибо, Гендальф, ты меня понял.
                                                    Ответить
                                                    • Кстати, а часто вы передаете is_trivially_destructible?

                                                      Просто если нет, то ведь смысла от быстрой очистки стека посредлством MOV нет
                                                      Ответить
                                                      • > Кстати, а часто вы передаете is_trivially_destructible?

                                                        В Сишке все-все-все структуры trivially_destructible. Именно поэтому я за «Си».
                                                        Ответить
                                                        • > Именно поэтому я
                                                          никогда не забываю close, fclose, petuh_destoroy и free в правильном порядке
                                                          Ответить
                                      • mov rsp, rbp
                                        pop
                                        
                                        ; или leave
                                        Твоё автоуничижение тебе конпилер сгенерит.
                                        Ответить
      • Вспомни ближние/дальние указатели в реальгном режиме с сегментацияей
        Ответить
        • Ага, помню. Для их поддержки пришлось нарушить несколько пунктов сишного стандарта.
          Ответить
          • Какие конкретно?

            Разве что ручной выбор между near и far указателями привернули.

            А в остальном сишный стандарт оставляет достаточно UB'ов и свободы, имхо.
            Ответить
      • На самом деле ни Гарварда ни фон Немана не существует. Пишеш на гарварде ниско уровневый интерпретер, и получаешь неймана. Запрещаещ писать в код, и получешь снова гарвард. И т.д.
        Ответить
        • Ну это были просто конкретные идеи построения компа. А потом кто-то уже начал натягивать сову на глобус.
          Ответить
    • Было обнаружено, что стаи скворцов структурированы больше, чем газ, но меньше, чем жидкость
      Ответить
      • Какой это ставит перед оператором вопрос: каким приемом решает вопрос о том, подлежат ли эти дочерние стаи энергосбережения?

        Не имеет значения, какими танкерами захватывает это дочернее сооружение которые могут носить на большой скорости огромную толщину составляющей, или их масса не превышает сотни тонн и миллионы килограммов но это дочернее сооружение на скорости между стаи составляющей. Но для таких стаи на них приходится заранее установить прием, при расчете по опыту потери энергии подлежат заметным повышениям, из-за чего это вообще возможно?
        Ответить
    • а вы польщзуетесь draw.io?
      Ответить
      • Я пользуюсь
        Ответить
        • десктопной или вебной?

          Я относительно недавно для себя открыл, и оно окончательно заменило мне визио. Что приятно, оно нативно умеет в svg.
          Ответить
    • бросай курить: https://pbs.twimg.com/media/FKSQlXPUUAIaBs9?format=jpg&name=900x900
      Ответить

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