знак на ассемблере
(эта запись будет интересна только программистам)
Расс Кокс рассказывает о супероптимизации - технике поиска самого быстрого куска кода путем полного перебора инструкций процессора (конечно, это работает только для очень коротких кусков кода). Любопытный пример там - самое быстрое воплощение функции знака (-1, 0 или 1 в зависимости от знака аргумента) на ассемблере 80x86. До такого вручную действительно додуматься нелегко:
cwd
neg ax
adc dx, dx
Здесь начальный аргумент лежит в ax, значение помещается в dx. Работает следующим образом: сначала cwd расширяет знак ax в dx, после чего в dx лежит -1, если аргумент отрицательный, а иначе 0. neg ax меняет знак ax, но это на самом деле неважно, а важно то, что эта инструкция помещает в флаг carry единицу, только если аргумент был ненулевой.
Наконец adc dx, dx складывает dx с самим собой, добавляет carry от второй инструкции, и помещает результат в dx. В результате выходит:
- если ax<0, то dx вначале -1, carry равен 1, результат равен -1*2+1 = -1 (во как!)
- если аx=0, то dx вначале 0, carry равен 0, результат 0*2+0=0
- если ax>0, то dx вначале 0, carry равен 1, результат 0*2+1=1
Красиво!
Расс Кокс рассказывает о супероптимизации - технике поиска самого быстрого куска кода путем полного перебора инструкций процессора (конечно, это работает только для очень коротких кусков кода). Любопытный пример там - самое быстрое воплощение функции знака (-1, 0 или 1 в зависимости от знака аргумента) на ассемблере 80x86. До такого вручную действительно додуматься нелегко:
cwd
neg ax
adc dx, dx
Здесь начальный аргумент лежит в ax, значение помещается в dx. Работает следующим образом: сначала cwd расширяет знак ax в dx, после чего в dx лежит -1, если аргумент отрицательный, а иначе 0. neg ax меняет знак ax, но это на самом деле неважно, а важно то, что эта инструкция помещает в флаг carry единицу, только если аргумент был ненулевой.
Наконец adc dx, dx складывает dx с самим собой, добавляет carry от второй инструкции, и помещает результат в dx. В результате выходит:
- если ax<0, то dx вначале -1, carry равен 1, результат равен -1*2+1 = -1 (во как!)
- если аx=0, то dx вначале 0, carry равен 0, результат 0*2+0=0
- если ax>0, то dx вначале 0, carry равен 1, результат 0*2+1=1
Красиво!