- 1
#define BSWAP16(x) ( (uint16_t)(((uint32_t)x)*(1 | 1 << 16) >> 8) )
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+1
#define BSWAP16(x) ( (uint16_t)(((uint32_t)x)*(1 | 1 << 16) >> 8) )
Надо наверно так, чтоб уж наверняка:
По крайней мере, в Open Watcom уже есть <stdint.h>.
У x86 есть несколько инструкций для 32-битных чисел, они используют пару регистров (DX и AX, например).
Потому что автор оставил такие метаданные в pdf-файле. Он ещё написа́л, что автора зовут gabriele.
Я ещё открыл для себя давно забытую инструкцию SHLD: сдвинуть содержимое регистра на N позиций влево, вдвинув в освободившиеся позиции биты из другого регистра. Есть аналогичная инструкция SHRD.
А ещё в плавпитухе есть 32-битное и 64-битное целое.
Но как с целым-то с ним оперировать не получится.
Но снимок в оперативке, сделанный инструкцией КУЛАК, выглядит так же, как обычное целое число.
x = BSWAP16(x++);
Собственно, по твоей аве это заметно.
В js никаких uint16_t нету.
> ((x << 8 | x >> 8)&0xFFFF) .toString(16);
Именно поэтому я за «js».
На самом деле касты говно, а такой код будет работать в любом сиподобном языке.
Сократил, проверь.
Очевидно же, что если ксорить какое-то говно два раза с одним и тем же говном, то ничего не поменяется
https://ideone.com/1KiivR Работает и в режиме компиляции (как макрос) и в режиме интерпретации.
В js тоже есть «union»
Есть инструкция xchg, ожидающая восьмибитные данные. Аргументами могут выступать два восьмибитных регистра либо восьмибитный регистр и указатель на память.
Итого: 2g@0G@2G@2G@2g@0g@0G@
21 байт. Длинновато вышло, зато в ASCII-кодах.
http://govnokod.ru/15764#comment419684
g@ –— это ah, [bx+40h]
G@ –— это al, [bx+40h]
http://www.club155.ru/x86cmdformats-modrm
PPDXD
А так придётся SP где-то ещё сохранять, а потом восстанавливать.
64-битный вариант (почему-то не работает):
https://ideone.com/jycvRV
А ты декомпильни этот код. 'D' - не инкремент. Это префикс REX.R
Какой багор )))
Надо запомнить, что у x86-64 однобайтовых инкрементов/декрементов нет, на их месте ненужные префиксы Рэкс-фас; PUSHA, POPA, BOUND отменили; на месте ARPL теперь MOVSXD; AAA, AAS, DAA, DAS, AAM, AAD отменили; префиксы сегментов отменили, за исключением FS, GS; пуш и поп для сегментных регистров тоже отменили; LES, LDS, CALL FAR, JMP FAR тоже отменили.
И зачем-то отменили опкод 82H, который никому не мешал.
Как вообще можно что-то делать без однобайтовых инкрементов/декрементов???
83H –— это операции с 16/32-битным регистром, у которых в качестве второго аргумента выступало 8-битное непосредственное, которое на лету дополнялось нулями до 16/32-битного. Было очень удобно, потому что не нужно было хранить в программе лишние нули.
А 82H –— это просто копия 80H.
https://ideone.com/2Z5MCE
Узнал две особенности x86-64:
1. У кучи инструкций непосредственный аргумент может быть максимум 32-битным. Старшая половина добивается нулями. Мне пришлось делать четыре 16-битных пуша, чтобы запушить 64-битное число.
2. У инструкций с mod-R/M нужно указывать префикс REX.W (H), иначе результат обрежется до 32-битного.
Как всё сложно...
https://ideone.com/6T9Ima
> fffUUfUU
Что-то мне не нравится pitush word 0x5555.
Есть альтернативный способ?
> вместо инкремента вычитать минус единицу
А через CWD/CDQ не получится?
Например
SUB AL, 85
SUB AL, 85
SUB AL, 85
Вот тут автор изобрёл компилятор, который получает EXE-файлы для «DOS», состоящие только из печатаемых ASCII-символов (включая заголовок):
http://tom7.org/abc/
https://sourceforge.net/p/tom7misc/svn/HEAD/tree/trunk/abc/
Такой экзешник можно передавать как текстовый файл.
Даже file не разгадал
А вот EXE-файлов, зожатых таким образом, я не видел. Tom7 — первый, кто придумал заголовки EXE составлять из печатаемых символов.
В странную эпоху живём.
Появились читабельные EXEшники.
Исчезли читабельные JSники.
Теперь JS имеет читабельность бинарного файла, зато обладает скоростью скриптового языка.
Миша Збыковски просил передать, что давно уже
cdq не ascii
Именно поэтому я за x86-32
https://stackoverflow.com/questions/14698350/x86-64-asm-maximum-bytes-for-an-instruction
«mov qword [rax + rcx + 0x11223344], 0x55667788», например, занимает 12 байт, а с 64-битным аргументом получится 16 (и ещё всякие префиксы могут быть же). Ну и как пишут на SO — 64-битный аргумент можно напрямую загружать в регистр.
В 64-битном режиме у «gcc» есть два соглашения о вызове: «sysv_abi» и «ms_abi». При «sysv_abi» первые 6 аргументов передаются через регистры (RDI, RSI, RDX, RCX, R8, R9), при «ms_abi» только четыре первых аргумента передаются через регистры (RCX, RDX, R8, R9). Плавающий питух передаётся через питушиный стек (до четырёх аргументов в случае «ms_abi» и до восьми аргументов в случае «sysv_abi»). Стек в обоих случаях чистит вызываемая функция. Нельзя портить RBX и RBP (а для «ms_abi» ещё и RSI и RDI) и четыре последних нумерных.
В 32-битном режиме вариантов способа вызова гораздо больше. «Fastcall» у разных компиляторов реализован по-разному («gcc» первые два аргумента передаёт через ecx и edx).
Мне больше всего понравилось, как сделали в «Watcom C»: там с помощью #pragma можно создать своё собственное соглашение, указав, через какие именно регистры нужно передавать аргументы и кто будет чистить стек.
Эта хуйня порождает очень весёлые баги в ring 0 (если пишешь своё ядро, например)... Её, конечно, можно отключить. Но для этого про неё надо знать.
Да тупо процессор во время обработки прерывания. Он же ничего не знает про эти ваши редзоны.
Я надеваю штиблеты и галстук-шнурок,
Я запираю свою дверь на висячий замок.
Вызывающая.
То есть можно создавать функции с переменным количеством аргументов, а вот сделать принудительный пуш/поп посредством каламбура типов не получится.
В общем-то это даже надёжней т.к. вызываемый видит обе границы аргументов. А в cdecl - только нижнюю.
Варианты реализации:
1. Патчить код (изменять байтик, следующий за опкодом RET). Для этого нужно снимать защиту.
2. Свитч-кейс, в каждой ветке которого будет RET N с соответствующим значением N.
3. Извлекать из стека адрес возврата, чистить стек, после этого делать джамп (ну или push+ret) на сохранённый в регистре адрес возврата.
А можно даже количество не передавать. Не дочитал все vararg'и - получай UB.
Кстати, а ведь ret и ret N спекулятивно возвращаются к вызывающему независимо от N и состояния стека? Т.е. вариант с push + ret будет более правильным, нежели jmp...
Сперва присунул, потом спросил?
…кроме ЗППП.
Пишут, что сервис славится нереальными задачами типа доставить еду на расстояние 4 километра за 14 минут. Напоминаю, что курьер пеший. За опоздание штраф.
https://habr.com/ru/news/t/448722/
Один комментатор уже вспомнил песню «16 тонн». Если кто-то не знает, это песня про США эпохи Великой депрессии:
https://ru.wikipedia.org/wiki/Sixteen_Tons
Имхо, страшнее когда так работают таксисты или газелисты. Зомбаки за рулём.
> нереально
Если верить гуглу, то КМС должен пробежать за это время 5км. Так что вполне реально.
С десятикилограммовым рюкзаком?
> Зомбаки за рулём.
Читал в какой-то книжке, что спящий водитель хуже пьяного: у пьяного есть хоть какая-то реакция, пусть даже с задержкой, а у спящего реакции на обстановку нет.
Ну да, это уже к спецназовцам...