Fasm вайбкодинг

Тема в разделе "FASM", создана пользователем f13nd, 31 мар 2026.

  1. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    2.153
    ## Потому что гладиолус.
    Я не знаю ни одной модели, которая бы хорошо писала на FASM. Они рожают жутких гомункулов на смеси французского с рязанским (масм, насм, возможно еще что-то). Исходников на фасме в интернете вообще мало, они имеют расширение .asm, а внутри обычно не написано, что это фасм. Поэтому выхлопы получаются "на каком-нибудь ассемблере". Нужны костыли, вот они:
    - Скрипт-ревьювер, которого суб-агент после изменений в исходнике сам применит на файл и из выхлопа узнает, в чем был неправ и как это исправить. Потому что Fasm в формулировках ошибок абсолютно беспощаден и руководствуясь ими даже живой человек не сразу поймет как исправить. Сама llm неохотно ищет ошибки в сгенерированном коде, пока не макнешь ее в них лицом. Скрипт как раз это и делает.
    - Справочники в каком-нибудь затейливом виде, чтобы llm могла затягивать информацию в контекст как можно меньшими порциями. У Roo Code не то чтобы очень богато с инструментами: больно смотреть как llm выкручивается командами powershell или python -c, чтобы найти что-то регулярками и выщемить порционно. Наилучший на мой взгляд вариант - Custom Tools Roo Code'а. Можно создавать свои инструменты на жабоскрипте, что-то типа MCP, но без лишних посредников.

    ## Костыли
    1. Скрипт-ревьювер (utility/fasm_reviewer.py). Отжимаем из мануала по фасму краткую справку по каждой директиве и каждому аспекту, складируем в .md-файл, потом просим llm изучить его и реализовать в скрипте проверку синтаксиса согласно этим сведениям. Пару дней возни и вот он, кривущий и убогий петон-скрипт, которого не касалась рука человека. Занятно наблюдать как суб-агент не одуплив чего этот скрипт от него хочет, начинает его чинить. И ведь чинит. Кстати всю жизнь использовал флаг 'writable', а тут llm макнула меня лицом в то, что такой директивы не существует. В мануале о ней ни слова: Гриштар советует использовать вариацию с британским акцентом 'writeable'. Но работают обе. Недокументированная фича.
    2. Справочник по Fasm (.roo/tools/fasm_manual.js, .roo/tools/fasm_manual.md). Из полученных маркдаунов в предыдущем пункте лепится справочник, потом показав llm пример использования Custom Tool'а, предлагаю написать такой же, но реализовав там методы выборки.
    3. Справочник по winapi (.roo/tools/winapi_manual.js, .roo/tools/winapi_manual_proc.md, .roo/tools/winapi_manual_struct.md, .roo/tools/winapi_manual_const.md). Потому что в исходнике на высокоуровневых ЯП, на которых llm в основном обучены, нет указаний в какой dll какая функция лежит. Сами Майкрософт тоже подложили свинью, налепив заголовков, которые не соотносятся с конкретными библиотеками. Поэтому llm приходится играть в угадайку. Часто проигрывает. Структуры знает, но боится вписывать. Лезет в папку с фасмом в надежде найти там. С константами та же история: имена знает, значения не очень. Поэтому скачав исходники бесплатного паскаля прошу llm сделать парсеры. По возможности выкорчевать весь паскализм, приведя к цэшному синтаксису. Почему не фасмосинтаксис? Потому что не надо, даже вредно: пришлось бы делать отдельные справочники для x86 и x64. Немного увлекается бесконечными копаниями в константах, но отдельной директивой для субагента вроде бы это чинится.

    ## Суб-агент Смит
    1. Планировщик /fasmp (.roo/commands/fasmp.md). Выкрутив занудство на максимум (режим Architect) разбивает описанную задачу на ряд элементарных. Если ты достаточно занудно описал задачу, поощряет занудство дополнительными вопросами. Сохраняет в plans/NN_%stagename%.md. Каждый план - субагент-имплементер, который что-нибудь внедряет и вызывает субагента-ревьювера: '
    **CRITICAL** Strictly follow the directives: .roo/commands/fasmr.md, Source file name: source_filename.asm'.

    2. Оркестратор /fasmw (.roo/commands/fasmw.md). Включает режим оркестратора, смотрит какие файлы есть в plans/ и запускает каждый в отдельном контексте.
    3. Ревьювер /fasmr (.roo/commands/fasmr.md). Запускает скрипта, смотрит выхлоп, чинит исходник до компилируемого состояния. Если состояние не достигнуто, опять чинит.

    ## /fasmp <prompt>, /fasmw, profit!
    Код (Text):
    1. /fasmp сгенерируй план по созданию классической игры "змейка" на фасм. Это должно быть x86 Windows приложение в окне, для отрисовки используй gdi. Управляться змейка должна кнопками wasd. Если змейка сталкивается со стеной или своим телом, игра должна оканчиваться, предлагать нажать пробел для начала игры заново. Недопустим поворот змейки сразу на 180 градусов. В левом верхнем углу экрана должен отображаться счет - число съеденных яблок. Цвет заднего фона - зеленый, цвет змейки - синий, цвет яблок - красный.
    Код (Text):
    1. /fasmw
    Screenshot 2026-03-31 183724.png
    изображение_2026-03-31_184644194.png
     

    Вложения:

    Rel, aa_dav и GRAFik нравится это.
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.365
    Дело не в отсутствии моделей, а в количестве и качестве кода для обучения. Как тебе стохастический попугай будет "выдумывать" твой любимый фасм, если он этого фасма толком не видел нигде? Как бы манипуляции контекстом, чтобы заставить модель "понимать" фасм через мануалы - это здорово, но вряд ли от этого возможен эффект достаточный, чтобы компенсировать отсутствие данных для обучения. Но в пол пятого ночи с интересом прочитал, спасибо.
     
  3. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    590
    Год или может два назад пытал нейронки на предмет чтобы они сделали алгоритм умножения на двух самых популярных 8-битных процессорах своего времени: MOS 6502 и Z80.
    Результаты сильно удручали. Даже поверхностного взгляда было достаточно чтобы понять что это как будто альцгеймер пытается вспомнить шпаргалку.
    При том что процессоры такие - эпичное прошлое - которое на гитхабах, имхо, должно встречаться не так уж и редко.
    Сейчас попытал дипсик:
    результат:
    Код (Text):
    1.  
    2. ; Процедура умножения беззнаковых байт
    3. ; MX    - первый множитель (1 байт)
    4. ; MY    - второй множитель (1 байт)
    5. ; R     - результат (2 байта) - младший байт по адресу R, старший по R+1
    6.  
    7.         ORG $0600           ; начало программы (можно изменить)
    8.  
    9. MX      DB $12              ; первый множитель (пример: 18)
    10. MY      DB $34              ; второй множитель (пример: 52)
    11. R       DS 2                ; резервируем 2 байта для результата
    12.  
    13. ;----------------------------------------------------------------
    14. ; Процедура умножения
    15. ;----------------------------------------------------------------
    16. MULTIPLY:
    17.         LDA #0              ; обнуляем младший байт результата
    18.         STA R               ; R (младший байт) = 0
    19.         STA R+1             ; R+1 (старший байт) = 0
    20.        
    21.         LDX #8              ; устанавливаем счетчик битов (8 бит)
    22.         LDA MX              ; загружаем первый множитель в аккумулятор
    23.        
    24. MULT_LOOP:
    25.         LSR A               ; сдвигаем младший бит в C (флаг переноса)
    26.         BCC NO_ADD          ; если бит = 0, пропускаем сложение
    27.        
    28.         ; если бит = 1, добавляем MY к результату
    29.         CLC                 ; очищаем флаг переноса перед сложением
    30.         LDA R               ; загружаем младший байт результата
    31.         ADC MY              ; добавляем младший байт множителя
    32.         STA R               ; сохраняем младший байт результата
    33.        
    34.         LDA R+1             ; загружаем старший байт результата
    35.         ADC #0              ; добавляем перенос от младшего байта
    36.         STA R+1             ; сохраняем старший байт результата
    37.        
    38. NO_ADD:
    39.         ; сдвигаем MY влево для следующего бита
    40.         ASL MY              ; сдвигаем MY влево (умножаем на 2)
    41.         DEX                 ; уменьшаем счетчик битов
    42.         BNE MULT_LOOP       ; продолжаем, если не все биты обработаны
    43.        
    44.         RTS                 ; возврат из процедуры
    45.  
    46. ;----------------------------------------------------------------
    47. ; Инициализация и запуск (опционально)
    48. ;----------------------------------------------------------------
    49. START:
    50.         JSR MULTIPLY        ; вызываем процедуру умножения
    51.         BRK                 ; останавливаем программу
    52.  
    Вот тут уже намного лучше - код _почти_ корректен, за исключением того, что двухбайтовость результата тут запорота - MY это байт, а его перед операцией надо превратить в слово и слово и прибавлять и сдвигать.
    Т.е. вывод опять неутешителен: ассемблер плохо поддаётся, даже исторический по которому должны быть сотни учебников в закромах электронных библиотек и примеров тоже должны быть тысячи от исторических до современных ретропроектов.

    Учитывая, что Диспсик гениально впитал, что 1С это подвид бейсика и генерит законченные примеры на нём с минорными легко диагностируемыми ошибками я думаю что в ассемблере проблема именно еще в том, что он плохо ложится в мозги. Что в человеческую нейронку что в искусственную - он просто плохо в нейронки укладывается. Не предназначен для этого. Синаптические связи плохо на него ложатся.
     
  4. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    2.153
    У меня буквально об этом и написано тремя предложениями дальше. Достаточен ли эффект - эта шляпа генерит полурабочий исходник минут за 30. Минут 20 отладки и он работает. Я понимаю, что у меня ушло бы на это больше времени. Критерий истины.
    Тебе нужно какой-то критерий валидности ввести. Сделать интерфейс на симулятор-отладчик ллмке, чтобы она могла проверять то, что пишет. В отладку оно умеет и само догадывается: для проверки правильности кода без подсказки создает отдельные семплы, либо пихает сразу в исходник print'ы, смотрит выхлопы, делает по ним правильные выводы. Главное чтобы у ллм была такая возможность. А в финале можно промтом заставить сделать конспект, чему новому оно научилось, чтобы потом кормить этими тезисами другие контексты.
     
  5. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.578
    Адрес:
    Russia
    Проверил GPT 5.2
    Код (Text):
    1.  
    2. ; Unsigned byte multiply
    3. ; Input:  MX = multiplicand (8-bit)
    4. ;         MY = multiplier   (8-bit)
    5. ; Output: R  = low byte of 16-bit product
    6. ;         R+1= high byte of 16-bit product
    7. MultiplyBytes:
    8.     lda #$00        ; Clear accumulator
    9.     sta R           ; Clear result low byte
    10.     sta R+1         ; Clear result high byte
    11.     ldx #$08        ; Set bit counter to 8 iterations
    12. @loop:
    13.     lsr MY          ; Shift multiplier right; bit 0 goes into carry
    14.     bcc @skip_add   ; If the bit was 0, skip adding multiplicand
    15.     clc             ; Prepare for addition
    16.     lda R           ; Load result low byte
    17.     adc MX          ; Add multiplicand into low byte
    18.     sta R           ; Store updated low byte
    19.     lda R+1         ; Load result high byte
    20.     adc #$00        ; Add carry from low-byte addition
    21.     sta R+1         ; Store updated high byte
    22. @skip_add:
    23.     asl MX          ; Shift multiplicand left for next bit position
    24.     dex             ; Decrement loop counter
    25.     bne @loop       ; Continue until all 8 bits are processed
    26.     rts             ; Return to caller
    27.  
     
  6. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    590
    Под копирку та же ошибка - MX это байт старшие биты из которого вываливаются при asl MX и 16-битный результат попросту неверен.
    Причём 1-в-1 повторил то что нагенерил ДипСик, хотя обрамление кода разное.

    А на самом деле вот это фрагмент:
    Код (Text):
    1.  
    2.     clc             ; Prepare for addition
    3.     lda R           ; Load result low byte
    4.     adc MX          ; Add multiplicand into low byte
    5.     sta R           ; Store updated low byte
    6.     lda R+1         ; Load result high byte
    7.     adc #$00        ; Add carry from low-byte addition
    8.     sta R+1         ; Store updated high byte
    9.  
    должен был быть примерно таким:
    Код (Text):
    1.  
    2.     clc             ; Prepare for addition
    3.     lda R           ; Load result low byte
    4.     adc MX_LOW          ; Add multiplicand into low byte
    5.     sta R           ; Store updated low byte
    6.     lda R+1         ; Load result high byte
    7.     adc MX_HIGH        ; Add carry from low-byte addition
    8.     sta R+1         ; Store updated high byte
    9.  
    складываем два 16-битных значения. И чуть ниже сдвигать надо так же MX_LOW и MX_HIGH влево как пару.
     
  7. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    590
    P.S.
    Сам сейчас освежил память в поисковике - а ведь есть альтернативный вариант и сразу же гуглится, когда сдвигаем мы результат в R, что требует лёгкой модификации алгоритма - мы тестировать начинаем со старших бит MY, если бит 1, прибавляем MX к R (как выше), и R в каждой итерации сдвигаем влево как 16-битное значение. То есть накапливаем результат от старших разрядов к младшим - это позволяет обходится одним 16-битным данным R и в нём проводить и сложения и сдвиги, но исключает ранний выход из цикла при обнулении множителя (его, впрочем, ИИ и в примерам выше не сделал).
    И это на самом деле первое что вылезло в гугле. То бишь ИИ как то прям захромал на ровном месте - такое ощущение, что он попытался взять пример с 8-битным результатом и самостоятельно расширить его до 16-битного результата, но всей мощи тысяч кластеров RTX 5060 24Гб недостаточно для того чтобы справится с 8-битным ассемблером из 70-х...
    --- Сообщение объединено, 3 апр 2026 ---
    Если он умножить два байта не может правильно я лично не стал бы даже пытаться из него выдоить результат на что-то более сложное.
     
    TermoSINteZ нравится это.
  8. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.578
    Адрес:
    Russia
    Он вообще не думает. Часто несет чушь.
    А самое забавное, когда пишешь типа "но ведь тут ошибка " и укзаываешь ему на ошибку, то он такой "Да и правда здесь ошибка" )))
     
  9. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    308
    ..у меня иногда дипсик вообще обижается, и ничего не отвечает. ;)
     
  10. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    590
    Ну давайте помучаем еще дипсика на предмет Z80:
    Всё далее - его ответ, я его внимательно прочитал и, конечно, в ужасе. Думаю тут найдутся бывшие спектрумисты которые смогут оценить всю глубину его грехопадения - ни одного вообще правильного варианта.
    Итак, наслаждайтесь:

    Вот эффективная процедура умножения двух беззнаковых байт для Z80:
    Код (Text):
    1.  
    2. asm
    3. ; Умножение двух беззнаковых байт
    4. ; Вход: A = множитель, C = множимое
    5. ; Выход: HL = произведение (16 бит)
    6. ; Разрушает: A, B, C, HL
    7. ; Размер: ~15 байт
    8. ; Время: ~112-164 тактов (зависит от данных)
    9.  
    10. Mul_Byte_Byte:
    11.     LD   HL, 0          ; HL = 0 (очистка результата)
    12.     LD   B, 8           ; B = 8 (счетчик битов)
    13.    
    14. Mul_Loop:
    15.     ADD  HL, HL         ; HL = HL << 1 (сдвиг результата влево)
    16.     SLA  C              ; C = C << 1, выдвигая старший бит в CF
    17.     JR   NC, Mul_Next   ; если бит = 0, пропускаем сложение
    18.     ADD  HL, DE         ; иначе HL = HL + A (добавляем множитель)
    19.    
    20. Mul_Next:
    21.     DJNZ Mul_Loop       ; повторяем для всех 8 битов
    22.     RET
    23.  
    Но есть проблема - в этом коде используется DE. Вот исправленная версия без лишних регистров:
    Код (Text):
    1.  
    2. asm
    3. ; Умножение двух беззнаковых байт (стандартный алгоритм)
    4. ; Вход: B = множитель, C = множимое
    5. ; Выход: HL = произведение
    6. ; Разрушает: A, B, C, HL
    7.  
    8. Mul_Byte_Byte:
    9.     LD   HL, 0          ; HL = 0 (результат)
    10.     LD   A, 8           ; A = 8 (счетчик битов)
    11.    
    12. Mul_Loop:
    13.     ADD  HL, HL         ; HL = HL << 1
    14.     SLA  C              ; C << 1, старший бит в CF
    15.     JR   NC, Mul_Next   ; если CF=0, пропускаем
    16.     ADD  HL, BC         ; HL = HL + B (добавляем множитель)
    17.    
    18. Mul_Next:
    19.     DEC  A              ; уменьшаем счетчик
    20.     JR   NZ, Mul_Loop   ; повторяем, если не ноль
    21.     RET
    22.  
    Но в этом коде есть тонкость: ADD HL, BC прибавляет BC, а не только B. Вот финальная корректная версия:
    Код (Text):
    1.  
    2. asm
    3. ; Умножение двух беззнаковых байт
    4. ; Вход: D = множитель, E = множимое
    5. ; Выход: HL = D * E (16 бит)
    6. ; Разрушает: A, B, D, E, HL
    7.  
    8. Mul_Byte_Byte:
    9.     LD   HL, 0          ; HL = 0 (результат)
    10.     LD   B, 8           ; B = 8 (счетчик битов)
    11.     LD   A, D           ; сохраняем множитель в A
    12.    
    13. Mul_Loop:
    14.     ADD  HL, HL         ; HL = HL << 1
    15.     SLA  E              ; E << 1, выдвигая старший бит в CF
    16.     JR   NC, Mul_Next   ; если бит = 0, пропускаем
    17.     LD   D, 0
    18.     ADD  HL, DE         ; HL = HL + D*256 + E? Нет, это неправильно
    19.    
    20. Mul_Next:
    21.     DJNZ Mul_Loop
    22.     RET
    23.  
    Вот самый правильный и эффективный вариант:
    Код (Text):
    1.  
    2. asm
    3. ; Быстрое умножение 8x8 = 16 бит
    4. ; Вход: A = множитель, C = множимое
    5. ; Выход: HL = A * C
    6. ; Разрушает: A, B, C, HL
    7.  
    8. Mul_Byte_Byte:
    9.     LD   B, A           ; B = множитель
    10.     LD   HL, 0          ; HL = 0 (результат)
    11.     LD   A, 8           ; счетчик = 8
    12.    
    13. Mul_Loop:
    14.     ADD  HL, HL         ; HL <<= 1
    15.     SLA  C              ; C <<= 1, CF = старший бит C
    16.     JR   NC, SkipAdd    ; если бит = 0, пропустить
    17.     ADD  HL, BC         ; HL += B (добавить множитель)
    18.    
    19. SkipAdd:
    20.     DEC  A              ; счетчик--
    21.     JR   NZ, Mul_Loop   ; повторять, пока не 0
    22.     RET
    23.  
    Примечание: Этот код корректен, так как ADD HL, BC прибавляет B к младшему байту HL (C в этом месте всегда 0 после сдвигов, кроме последних операций, но это допустимо).
    Альтернативный вариант (таблица умножения):
    Код (Text):
    1.  
    2. asm
    3. ; Умножение через таблицу (быстро, но требует памяти)
    4. ; Вход: A = множитель, C = множимое
    5. ; Выход: HL = A * C
    6.  
    7. Mul_Byte_Byte_Table:
    8.     LD   H, MulTable >> 8    ; старший байт таблицы
    9.     LD   L, A                ; L = множитель
    10.     ADD  HL, HL              ; HL = множитель * 2
    11.     ADD  HL, HL              ; HL = множитель * 4
    12.     ADD  HL, HL              ; HL = множитель * 8
    13.     LD   A, C                ; A = множимое
    14.     ADD  A, L                ; A = множимое + смещение
    15.     LD   L, A
    16.     LD   A, (HL)             ; младший байт результата
    17.     INC  H
    18.     LD   H, (HL)             ; старший байт результата
    19.     LD   L, A
    20.     RET
    21.  
    22. ; Таблица 256x256 = 64KB (слишком большая для большинства систем)
    23. ; Этот метод не рекомендуется из-за размера
    24.  
    Рекомендация: Используйте первый вариант (алгоритмический) - он компактный и достаточно быстрый для большинства приложений на Z80.
     
  11. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    2.153
    - Смотрите как можно решать проблемы несовершенства ллм и добиваться от них нужного результата
    - Ллм гавно, они из коробки вообще ничего не могут. Смотри, я два промпта написал и не получилось.
    - Тебе надо было сделать так и так.
    - Ллм гавно, я даже пытаться не буду. Лучше покажу-ка я еще раз как ллм из коробки ничего не могут.
     
  12. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.578
    Адрес:
    Russia
    Ну, можно и пытаться да, но чаще всего быстрее самому написать.
    Либо после каждой написаной ллм функции - делать тесты. покрывать 146 процентов
     
  13. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    595
    f13nd,

     
  14. Research

    Research Active Member

    Публикаций:
    1
    Регистрация:
    6 янв 2024
    Сообщения:
    455
    Нет никаких LLM. Внутри сидят тысячи китайцев которые не могут в fasm.
    Власти скрывают, чтобы не было скандала. Они сами себя загнали в тупик.
    Думали что все заработает, полетит. Как видите не полетело.
     
    Последнее редактирование: 3 апр 2026
  15. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    2.153
    Возможно я че-то неправильно делал. Вообще без придури, тупо дал мануал посмотреть.
    изображение_2026-04-03_133203750.png
     
  16. deepfacer

    deepfacer New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2024
    Сообщения:
    6
    Ahimov нравится это.
  17. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    2.153
    Иронично, что "штука, которая не может умножить два числа" знает матчасть:
     
  18. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    595
    deepfacer,

    Системные совпадения, прямо как эво :)

    вот
     
    TermoSINteZ нравится это.
  19. aa_dav

    aa_dav Active Member

    Публикаций:
    0
    Регистрация:
    24 дек 2008
    Сообщения:
    590
    Насчёт матчасти на примере с Z80 у дипсика всё тоже плохо, он выдал:
    Но это грубо неверно - регистровая пара BC к регистровой паре HL прибавляется ровно так как написано - B к H, C к L (плюс переносы), а L это от Low, а H это от High.
    В общем всё наоборот.
    Судя по такому утверждению насчёт машинного кода этого у LLM этой в голове ну прям каша. Неупорядоченно всё и по полочкам разложено вхлам плохо.
     
  20. deepfacer

    deepfacer New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2024
    Сообщения:
    6
    Обрезаем 1450 до одного байта, удаляем знаковый бит - получится 42.
     
    Ahimov нравится это.