- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
function toHex(this: TypeOf<1>) {
return "hex";
}
function main() {
print((5).toHex());
print("done.");
}
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
−2
function toHex(this: TypeOf<1>) {
return "hex";
}
function main() {
print((5).toHex());
print("done.");
}
решил добавить прикольного кода из C# в TypeScript Compiler ... красиво получилось? (тем кто еще не знает где искать компилятор https://github.com/ASDAlexander77/TypeScriptCompiler)
2[ptr] будет uint16_t или int?
Далее, ты прибавляешь к указателю два. int там точно не будет: будет uint16_t, потому что ptr это укзаатель на uint16_t
ну и это без оптимизаций что-то gcc чудит и из регистра в регистр перекидывает всё
mov [OFFSET ...], %rax
mov %rax, [OFFSET ...]
А два раза слово растягивать -- хрень какая-то.
прям флюш на стек?
Кстати, а почему никто не делает пуш? Почему всегда ложат переменные по смещению?
SP берегут?
А нафига? С оптимизациями ведь легче читается, меньше воды.
Или он с оптимизациями всё это выбросил и оптимизнул до ret? )))
Хуй знает как это у тебя так получается.
Без оптимиизации обычно ты видишь какая строчка сишки во что компилца.
Вот переменная ложится на стек по смещению от bp, вот прибавляют константу к значению, поклав его в AX, вот ret.
В оптимизированном варианте ничего этого может и не быть вообще
Он очень стабильный, в нём нету багов конпелятора, он не раскрывает потенциал большинства UB'ов. Да и мапается 1:1 на исходник, что позволяет не лазить в асм.
На практике разбор асма всегда идёт на релизной сборке.
А ты вот прямо ищещь UB посредством чтения асма с -O2?
Ну вот и надо изучать их на релизном билде, чтобы видеть как они реально выглядят в коде...
Судить о конпеляторе по О0 -- это как судить о тян по резиновой копии.
Если случилась какая-то неведомая ёбаная хуйня и я на уровне исходников не понимаю что происходит (или их вообще нету) -- это в 99.99% случаев релизная сборка с оптимизациями.
Увы, умение читать дебажный код бесполезно на практике по описанным выше причинам. Если у тебя что-то крашится в дебаге, то ты почти всегда понимаешь причину не залезая в асм. Особенно если санитайзеры включены и ошибки ловятся по месту возникновения, а не когда засранную память прочитают.
Я просто последний раз в живой асм лазил чтобы выдрать из RAX возвращаемое значение какой-то хуйни, которую через сурс дебагер было не высосать. Но я высокоуровневый питушок, ближе к жаваговну и скриптоговну, так что это не удивительно
Да, умение читать релизный асм тоже требуется не часто.
Но умение читать дебажный асм требуется чуть реже, чем никогда. Ибо если проблема не решается на уровне исходников, то она в большинстве случаев* возникла в релизной сборке с оптимизациями и читать придётся именно оптимизированный асм.
* Была пара кейсов когда надо было изучить именно отладочную сборку, но на них никогда не налетишь если не будешь пилить свой рантайм.
...кроме учебных целей, когда ты пытаешься в голове замапать семантику няшной с семантикой асма.
Причем речь не о реальных компиляторах, а об идеальном мире, когда ты только изучаешь как стек работает, итд
Просто надо смотреть его на небольших примерах, а не на реальном коде.
> изучаешь как стек работает
Ну а тут, возможно, лучше взять какую-нибудь AVR'ку и запилить для неё что-то вручную прям на асме. У неё очень няшный асм, намного логичнее всех этих х86. И это не какое-то там легаси из музея, а вполне актуальная железка, которую юзают в продакшене.
Хотя всегда можно заказать нейтральный march
>AVR
Я никогда не писал под AVR, я вообще в нативном (не JVM) коде за пределы x86 вылазил только в ифончики, и писал под них на обжс и сишке (ну там пара API у ябла была на чистой сишке) так что и асма его не знаю.
Ну вот сравни какой-нибудь xor под amd64 в релизе и в дебаге. Какой из них проще понять новичку?
В релизе будут mov, xor и ret. Легко объяснить, зачем нужна каждая из них. А теперь объясни новичку назначение всей той хуйни, которая нагенерилась в дебаге...
Да, конпелятор может поюзать какую-нибудь lea для сложения или умножения на константу, да он может превратить x ? 42 : 100500 в весьма загадочную конструкцию. Но что-то совсем заумное генерить он не будет. Чего не скажешь о дебаге, в котором можно встретить и канарейку для защиты стека и какой-нибудь nop на ровном месте, о назначении которых тебе не каждый гуру расскажет.
Почему оптимизнутый код лучше для изучения?
Если смотреть на небольшую функцию, то в ней не будет всех этих фреймпоинтеров, прологов-эпилогов и прочего хлама. Там будут только инструкции, которые выполняют реальную работу. И это круто т.к. не придётся изучать всё сразу.
А потом уже можно сделать более сложный пример и посмотреть как конпелятор начинает пользоваться стеком. При этом ты уже знаешь как базовые инструкции работают и тебе легче понять новые фишки.
В дебажном коде придётся сразу объяснять весь этот обвес.
К примеру, рекомендую посмотреть, во что компилируется
с О3 и О0.
Причём на amd64 дебажный код особенно гротескный: принимает аргумент в регистре, а потом помещает его в локалку.
Кстати, в асме под BIOS и DOS то все переменные передавались через регистры, это паскале и сишке их начали через стек передавать (ну и в 32 тоже в некоторых конвеншенах вроде) а потом всё вернулось на круги своя
У тебя есть: входной параметр в edi.
Тебе надо: поместить его в eax
Решать эту непосильную задачу в шесть строчек, это слегка перебор.
А без оптимизаций получается:
Нет конечно. Ты ведь запретил конпелятору это делать. Ты сказал ему генерить дословную хуйню, которая будет мапаться 1:1 на сишку чтобы отладчику удобнее было бряки ставить и значения переменных смотреть.
Да, O0 заточено именно под отладчик, а не под чтение человеком.
1) Стандартизированные фреймы на регистре rbp. Самому коду они нахуй не нужны, но они очень важны для отладчика. Иначе парсинг стека вызовов встанет раком на любом незнакомом модуле без символов.
2) Сохранение всех аргументов на стек. Очень важная вещь, без которой значения аргументов для какой-нибудь функции в середине стека не найти.
3) Дословная трансляция кода. Чтобы бряки и пошаговое исполнение работали интуитивно. Одна строчка -- один фрагмент кода.
4) Всякие дополнительные проверки чтобы как можно раньше ловить ошибки.
Т.е. это не просто "код без оптимизаций", это код максимально заточенный под символьную отладку. И раздутый за счёт этого.
З.Ы. gcc даже позволяет себе немножко оптимизировать на O0, если это не аффектит описанное выше.
Лол, даже lea вместо add юзает на О0. И выражения в духе a * 2 + b *2 упрощает.
Это какой-то чрезвычайно нестабильный радикал получается. Ты как его получил?
Такая хуйня получается. Что-то подсказывает, что даже если она может существовать, то просуществует недолго.
Ну и изомер с (ОН) присоединённый к нижнему углероду...
https://en.wikipedia.org/wiki/Cyclopentadiene
Замещаешь один H на OH и получаешь спирт.
Хотя четырёхчленные кольца, как у тебя, тоже нестойкие.
В Win32 использовалось соглашение stdcall — всё через стек, в Win16 — pascal, всё тоже через стек. Хотя msvcrt.dll использовала соглашение cdecl (тоже через стек, но аргументы в другом порядке).
А в статических библиотеках соглашений было выше крыши.
В Watcom C было два набора стандартных библиотек: для передачи параметров через стек и для передачи через регистры.
Регистры vs стек — это два стула. Если ты вызываешь функцию из функции, тебе всё равно придётся сохранять контекст функции в стеке. Говорят, старые фортраны так не умели (передавали аргументы через глобалки?), поэтому в них рекурсия была запрещена, но это вроде давно исправили.
Да, но сохраняется намного меньше данных, чем в старых соглашениях.
Многие аргументы тупо не доживают до вызова. Зачем их сохранять на стек?
И функции которые зовут другие функции обычно "холодные". А горячим как раз достаются аргументы в регистрах.
Это да. И надо понимать когда юзать caller saved регистр (он не переживёт вызовы), когда callee saved (оригинальное значение придётся сохранить на стек, зато он переживёт вызовы), а когда ячейку на стеке.
Т.е. частоту использования ещё надо понимать.
Забавно, что 16 битный ISA делали для рукописного асма, а 64 уже скорее для компиляторов
Да вот кстати нет...
Простые функции писать даже легче т.к. всё в регистрах и не надо думать о стеке.
Реальная жопа начинается когда надо позвать сишную функцию из асма. Но это очень редко надо.
В дебажной сборке всё работало т.к. конпелятор юзает только 3-4 регистра и флашит всё на стек.
В релизной сборке всё поломалось т.к. оптимизатор посчитал, что значение некоторых регистров не испортится во время исполнения вставки. А она зовёт сишную функцию, которая их портит.
Т.е. изучать дизасм и отлаживать пришлось именно на релизной сборке. Почему? Потому что конпелятор раскрывает свой потенциал только в релизной сборке.
И это круто!
В отладочной сборке весь смысл функции тонет на фоне этой ебучей игры в напёрстки.
А в релизе поток данных намного лучше видно, имхо. Конпелятор старается держать значение в одном регистре от начала до конца.
Из джвух зол выбирают меньше, в общем. А если задача решается на уровне исходников -- я в асм не полезу, само собой. И в дебажной сборке она, как правило, и решается на уровне исходников т.к. кодогенерация там совсем тупая с минимумом багов и UB'ов.
но лучше всего просто юзать argc
Именно поэтому я за "Си"
Ох, какой удар по шее ждал бы тебя, будь ты реальнее и ближе.
Стыдно!
Невероятное проишествие! Человек нашел в ПРОДАКШЕН коде БАГ.
Такого раньше НЕ МОГЛО БЫТЬ В ПРИНЦИПЕ утверждает автор с 12-ю годами опыта на пе ха пе.
НАЧАЛАСЬ НОВАЯ ЭПОХА
Начну с самого рождения. Кстати о рождении: у нас родились на полу... Или хотя это мы потом расскажем.
Говорю прямо:
Дочь Патрулева родилась в субботу. Обозначим эту дочь латинской буквой М.
не спят они, а впрочем нет,
конечно спят и видят сон,
как будто в дверь вошел Иван,
а за Иваном управдом,
держа в руках Толстого том
"Война и мир", вторая часть...
А впрочем нет, совсем не то,
вошел Толстой и снял пальто,
калоши снял и сапоги
и крикнул: Ванька, помоги!
Тогда Иван схватил топор
и трах Толстого по башке.
Толстой упал. Какой позор!
И вся литература русская в ночном горшке.
Можно ещё «Goblin Slayer» ему посоветовать.
она от природы тян
именно потому она и не разбиратеся в аниме
А в этой спрашивают о наличии хуя и дате окончания ВУЗа?
она от природы тян
именно потому она и не разбиратеся в аниме
- как тебе я?
- лучше, чем предыдущая
В настоящее время в моих ресторанах едят подобных тебе. И тебе не миновать этой участи.
Еще можно так ответить:
"Ну знаешь, мне выбирать не приходится"
Или
"С пивом потянет"
Сообщается, что одним из главных преимуществ нового двигателя юноша считает его работу на топливе любого вида. «Представляете у вас в машине будет кнопочка и вы такие — хочу 92-й бензин, но остался день до зарплаты, поэтому заправлюсь 80-м», — пояснил молодой человек.