Comments 14
Достаточно посмотреть свой код, который ты писал год, два, три назад. :)
тут надо ещё добавить исходные коды яндекса :)
Мне кажется, или в приведенном коде CERN httpd переполнение буфера при попытке раздать файл размером 100 десятичных гигабайт? Такой исторический код надо закопать и никогда на него не смотреть - это совсем другие языки (даже если это C), совсем другие требования, другая экспертиза. По современным меркам это один сплошной антипаттерн.
Разработчик никому ничего не должен!
А где исходники Doom Engine? Безусловный шедевр
Шедевральная вещь – это исходный код программы-монитора Apple II, написанный Возняком. Я многое в своё время из него почерпнул, разбирая построчно, благо, он был неоднократно опубликован. Например, чтобы пропустить следующую команду размером 2 байта, не тратя ещё 2 байта на минимальную команду перехода, Возняк использовал 1 байт с подходящим кодом команды, который вместе со следующей 2-байтовой командой образовывал безвредную 3-байтовую команду (бывшая команда становилась полем данных новой команды). Так он каждый раз экономил 1 байт за счёт отказа от уровня абстракции ассемблера и работы на уровне голого машинного кода. И весь монитор умещался в ПЗУ размером 2 килобайта (а этот монитор включал набор процедур, как сейчас сказали бы, bios, плюс дизассемблер и собственный командный язык).
1 байт с подходящим кодом команды, который вместе со следующей 2-байтовой командой образовывал безвредную 3-байтовую команду
А можно немного более развернуто? НЯП в эту конструкцию должно быть 2 точки входа, где-то должны быть jmp (ненулевого размера) для перехода?
Мне попадалась интересная конструкция передачи параметров в функцию через PC
call function
.data Hello, World\0
// continue execution here
.label function
pull ax // вынимаем из стека указатель на Hello, world
// обрабатываем строку до \0
// AX теперь указывает на \0, который заодно NOP в 8080
jmp ax
Экономятся инструкции push перед вызовом функции, pull внутри функции, и jmp вместо ret. Но код вперемешку с данными, никаких early return, никакой кроссплатформенности. Удобно передавать только константные zero-terminated строки. Вряд ли это можно ещё где-то использовать.
Например, так вот (это, правда, из соседнего кода, AppleSoft BASIC):
db57: a9 20 OUTSP lda #‘ ’ ;print a space
db59: 2c db #$2C ;skip over next line
db5a: a9 3f OUTQUES lda #‘?’ ;print question mark
; Print char from A-reg
db5c: 09 80 OUTDO ora #$80 ;print A-reg
db5e: c9 a0 cmp #$a0 ;control chr?
db60: 90 02 bcc LDB64 ;skip if so
db62: 05 f3 ora FLASH_BIT ;=$40 for FLASH, else $00
db64: 20 ed fd LDB64 jsr MON_COUT ;ANDs with $3F (INVERSE), $7F (FLASH)
db67: 29 7f and #$7f
db69: 48 pha
db6a: a5 f1 lda SPEEDZ ;complement of speed #
db6c: 20 a8 fc jsr MON_WAIT ;so SPEED=255 becomes A=1
db6f: 68 pla
db70: 60 rts
Если мы вызываем подпрограмму OUTQUES по адресу $db5a, то загружаем в аккумулятор код вопросительного знака и уходим дальше в подпрограмму печати произвольного символа из аккумулятора OUTDO, которая находится ниже. А если мы вызываем подпрограмму OUTSP по адресу $db59, то мы загружаем в аккумулятор код пробела, выполняем машинную команду $2c, которая вместе со следующей командой складывается в бесполезную инструкцию тестирования битов bit $3fa9, и опять-таки уходим на код OUTDO. Таким образом, на три точки входа с различными параметрами в печать символа мы потратили всего 5 байтов. Хотя в мнемонике ассемблера мы должны были бы вместо db #$2c поставить двухбайтовый условный переход, например, bne *+2, или даже, рассуждая тупо, трёхбайтовый безусловный – jmp $db5c.
Сам код OUTDO здесь использует подпрограмму монитора MON_COUT для печати символа, но перед этим применяет к коду символа маску, установленному режимами вывода INVERSE и FLASH, а также делает задержку печати, установленную режимом SPEED= (это всё фишки Бейсика).
А как же легендарный алгоритм обратного корня из Quake III Arena?
float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
return y;
}
В разные времена были разные приоритеты. То на чем экономили 30 лет назад не имеет смысла сейчас.
Исторические исходные коды, с которыми должен быть знаком каждый разработчик