НОВЫЙ ОМЕРЗИТЕЛЬНЫЙ БАГ ПРОЦЕССОРА X86

x86 ТУПИТ ВСЕГДА.

НОВЫЙ-СТАРЫЙ-ВЕЧНЫЙ, ТУПОЙ БАГ В КАЖДОМ x86. (c) Oleg E. Tereshkov 2014

Нет рабства безнадёжнее, чем рабство тех рабов, кто сам себя считает свободным от оков. Гёте.

Iczelion: "Добро пожаловать в мир, где программист - хозяин компьютера, а не наоборот". "Ну-ну",- я.

Рад приветствовать вас, коллеги. Огромная благодарность всем, кто нашёл для себя возможным ознакомиться с моим скромным, неожиданным и печальным открытием.

В феврале 2015 эта работа была предложена высшему руководству INTEL, AMD и редколлегии российского журнала Хакер. Но такого рода приобретения корифеев не интересуют. Прошло уже целых 9 месяцев. Я думаю, вполне достаточно, чтобы им растелиться, ну хоть чем-нибудь, наконец. Нет - так нет. Статья ваша, знакомьтесь.

Вместо предисловия. Очень легко валить всё на туманы в брянских лесах, на внезапные снегоуборочные машины на взлётной полосе, на сонных авиадиспетчеров, пьяных капитанов круизных океанских лайнеров, российских рецидивистов, украинских националистов, донецких сепаратистов, якобы сбивших малайзийский боинг. Ещё легче обвинить во всём уже мёртвых, якобы чокнутых французских пилотов и таких же, оставшихся на земле, якобы чокнутых их подружек. Но очень тяжело признавать реальные дефекты реального процессора x86, встроенного повсюду и безудержно растиражированного миллионами экземпляров.

Так давайте же, братия, отимеем процессор x86 от INTEL и AMD по полной, а российский журнал Хакер, от зависти, пусть кусает себе локти и всё, до чего только, сам у себя же и дотянется.

Если кратко, то новый-старый-вечный, открытый мной, тупой баг x86 заключается в резком, до 94 раз, замедлении программы от одного лишь изменения порядка / очерёдности расположения переменных, при объявлении их в тексте исходника и / или значений самих этих переменных. Чего в норме не должно быть.

Для нормального процессора, ячейки памяти № 1 и № 2 ни чем не отличаются, друг от друга. А для x86 - отличаются. Для нормального процессора, не имеет значения лежит ли в ячейках памяти № 1 и № 2 число 1,2,3 или 255. А для x86 - имеет.

Вот формальный пример:

temp1=1

temp2=2

temp3=3

и

temp1=1

temp3=3

temp2=2

Или:

temp2=2

temp1=1

temp3=3

и

temp2=2

temp3=3

temp1=1

Или:

temp3=3

temp1=1

temp2=2

и

temp3=3

temp2=2

temp1=1

Для вас, всё это - одно и то же. И для меня. А для x86 - нет. Во всех шести случаях, скорость выполнения последующей, одной и той же программы может быть другой.

Или если:

temp1=1

temp2=2

то temp1+temp2 на x86 будет выполняться за одно время, а temp2+temp1 - за другое. Ещё больше разница будет, если изменить temp1=2, а temp2=1.

Не верите?

Вот прототип на Си:

// Speed_max.c

//(c) Oleg E. Tereshkov 2014

#include <stdio.h>

#include <conio.h>

//-------------------

int temp0,temp1,temp2,temp3,\

temp4,temp5,temp6,temp7,\

temp8,temp9,temp10,temp11,\

temp12,temp13,temp14,temp15,\

temp16,temp17,temp18,temp19,\

temp20,temp21;

//----------------------------------

//-------------MAIN-----------------

//----------------------------------

int main (void){

L1: temp11=1;temp12=5;temp13=1;

temp14=4;temp15=2;temp16=3;

temp17=4;temp18=2;temp19=5;

temp20=3;temp21=2;

temp1=temp2=temp3=temp4=\

temp5=temp6=temp7=temp8=\

temp9=temp10 = 0x7fffffff;

temp0=clock();

while (temp10 > 0) {

temp1=temp1 - temp11;

temp2=temp2 - temp12;

temp3=temp3 - temp13;

temp4=temp4 - temp14;

temp5=temp5 - temp15;

temp6=temp6 - temp16;

temp7=temp7 - temp17;

temp8=temp8 - temp18;

temp9=temp9 - temp19;

temp10=temp10 - temp20;

//-------(0)карусель(0)-------

temp21=temp20;temp20=temp19;

temp19=temp18;temp18=temp17;

temp17=temp16;temp16=temp15;

temp15=temp14;temp14=temp13;

temp13=temp12;temp12=temp11;

temp11=temp21; }

temp1=clock();

temp1=temp1 - temp0;

printf("%d\n", temp1);

goto L1;

}

Простейший, наглядный алгоритм, который, я уверен, в комментариях не нуждается и комментирует сам себя.

----------------линия+отреза_1---------------

Но дабы в дальнейшем устранить любые споры и разногласия, связанные с неочевидными особенностями конкретного компилятора Си, специально для всех вас, я переписал эту простейшую программу на ассемблере Fasm:

;Programm Speed_me_1.asm for Fasm

;(c) Oleg E. Tereshkov 2014

;//-------------macro-------------//

macro library [label,string]

{ forward

local _label

dd 0,0,0,rva _label,rva label

common

dd 0,0,0,0,0

forward

_label db string,0 }

macro import [label,string]

{ forward

local _label

label dd rva _label

common

dd 0

forward

_label dw 0

db string,0 }

;//------------endmac-------------//

format PE console

entry start

;//-------------code-------------//

section '.code' code readable executable

start: nop

lbl0: mov eax, 7fffffffh

mov [temp1], eax

mov [temp2], eax

mov [temp3], eax

mov [temp4], eax

mov [temp5], eax

mov [temp6], eax

mov [temp7], eax

mov [temp8], eax

mov [temp9], eax

mov [temp10], eax

call [clock]

mov [temp0], eax

lbl1: cmp [temp10], 0

jle lbl2

mov eax,[temp1]

sub eax, [temp11]

mov [temp1], eax

mov ecx,[temp2]

sub ecx, [temp12]

mov [temp2], ecx

mov edx,[temp3]

sub edx, [temp13]

mov [temp3], edx

mov eax,[temp4]

sub eax, [temp14]

mov [temp4], eax

mov ecx,[temp5]

sub ecx, [temp15]

mov [temp5], ecx

mov edx,[temp6]

sub edx, [temp16]

mov [temp6], edx

mov eax,[temp7]

sub eax, [temp17]

mov [temp7], eax

mov ecx,[temp8]

sub ecx, [temp18]

mov [temp8], ecx

mov edx,[temp9]

sub edx, [temp19]

mov [temp9], edx

mov eax,[temp10]

sub eax, [temp20]

mov [temp10], eax

;-------(1)карусель(1)-------

mov eax,[temp20]

mov [temp21], eax

mov ebx,[temp19]

mov [temp20], ebx

mov edx,[temp18]

mov [temp19], edx

mov ecx,[temp17]

mov [temp18], ecx

mov eax,[temp16]

mov [temp17], eax

mov ebx,[temp15]

mov [temp16], ebx

mov edx,[temp14]

mov [temp15], edx

mov ecx,[temp13]

mov [temp14], ecx

mov eax,[temp12]

mov [temp13], eax

mov ebx,[temp11]

mov [temp12], ebx

mov edx,[temp21]

mov [temp11], edx

;-------(1)карусель(1)-------

jmp lbl1

lbl2: call [clock]

sub eax, [temp0]

push eax

push temp_s

call [printf]

add esp, 8

jmp lbl0

;//-------------idata-------------//

section '.idata' import data readable writeable

library crtdll, 'crtdll.dll'

crtdll:

import printf,'printf',\

clock, 'clock'

;//-------------data-------------//

section '.data' data readable writeable

temp0 dd 0h

temp1 dd 0h

temp2 dd 0h

temp3 dd 0h

temp4 dd 0h

temp5 dd 0h

temp6 dd 0h

temp7 dd 0h

temp8 dd 0h

temp9 dd 0h

temp10 dd 0h

temp11 dd 1

temp12 dd 5

temp13 dd 1

temp14 dd 4

temp15 dd 2

temp16 dd 3

temp17 dd 4

temp18 dd 2

temp19 dd 5

temp20 dd 3

temp21 dd 2

temp_s db 25h,64h,0ah,0

У всех работает? Я надеюсь. Карусель можно переписать и так:

;-------(2)карусель(2)-------

mov eax,[temp11]

mov [temp21], eax

mov ebx,[temp12]

mov [temp11], ebx

mov edx,[temp13]

mov [temp12], edx

mov ecx,[temp14]

mov [temp13], ecx

mov eax,[temp15]

mov [temp14], eax

mov ebx,[temp16]

mov [temp15], ebx

mov edx,[temp17]

mov [temp16], edx

mov ecx,[temp18]

mov [temp17], ecx

mov eax,[temp19]

mov [temp18], eax

mov ebx,[temp20]

mov [temp19], ebx

mov edx,[temp21]

mov [temp20], edx

;-------(2)карусель(2)-------

Время прогона программы не изменится и составит примерно 13350 мс. С этого момента, я позволю себе конкретные числа. Время везде в миллисекундах, процессор - AMD Athlon(tm)XP 2500+ 1.83Ггц, память - 400Мгц, система - XP3.

(Для особо одарённых, но не особо обременённых излишними извилинами дебилов, на всякий случай, замечу, что приведенные в данном описании замеры времени верны только для моей системы. У вас они будут и должны быть другими, это - ничего не значащие детали. А вот пропорции и тенденции для (одноядерных и практически всех духядерных) процессоров x86 сохранятся полностью. И это - действительно важно.)

Если карусель переписать так:

;-------(3)карусель(3)-------

mov eax,[temp21]

mov [temp20], eax

mov ebx,[temp20]

mov [temp19], ebx

mov edx,[temp19]

mov [temp18], edx

mov ecx,[temp18]

mov [temp17], ecx

mov eax,[temp17]

mov [temp16], eax

mov ebx,[temp16]

mov [temp15], ebx

mov edx,[temp15]

mov [temp14], edx

mov ecx,[temp14]

mov [temp13], ecx

mov eax,[temp13]

mov [temp12], eax

mov ebx,[temp12]

mov [temp11], ebx

mov edx,[temp11]

mov [temp21], edx

;-------(3)карусель(3)-------

начнутся чудеса. И для Си-компиляторов, тоже. Время прогона сразу увеличится до 33500 - в 2.53 раза. Кому не бросается в глаза, в этом варианте переменные temp11-temp21 заполняются числом 2. Среднее арифметическое temp11-temp20 изначально равно 3. 3/2=1.5 и время прогона должно составлять 13250 x 1.5=19875. А у нас 33500. Думаю, что у вас нет разумного объяснения почему.

Давайте присвоим temp21=3. И сделаем ещё один прогон для (3)карусель(3). Время - 22250. Никак не 13250. Почему? Мой ответ - мной выявлен новый-старый, врождённый дефект, баг процессоров x86. Так грубо - с гарантией, проявляется он во всех одноядерных моделях x86 без исключения, вплоть до Pentium Mobile (проверьте) и большинстве двухядерных. И называется - ДЕФЕКТ О.Е. ТЕРЕШКОВА ДЛЯ ПРОЦЕССОРОВ x86.

Кое-кто скажет, что приведенные выкладки неправомерны. И в таких длинных и путанных циклах могут быть трудно выявляемые циклические же накладки и совпадения.

Хорошо. Ассемблер - не Си. В ассемблере FASM всё очевидно. Давайте вернёмся к первому варианту (1)карусель(1), а всем переменным temp11-temp21 присвоим значение 3. Результат - 13250 мс. Никак не 22250.

Прав я, время выполнения программы на процессоре x86 непредсказуемым образом зависит от величины и места расположения конкретных переменных в конкретном, готовом конечном коде. Который полностью и непредсказуемо, в этом отношении, может отличатся от того, что написано в исходнике. Особенно в случае си-компилятора и т.п.

Если скорость выполнения программы в разы зависит от порядка расположения переменных в памяти, то глупо и бессмысленно сравнивать между собой равноценные, не имеющие грубых внутренних дефектов компиляторы для процессоров x86 по быстродействию конечного кода. И те, кто платит за какие-то там синтетические супер-пупер тесты, просто выбрасывают деньги в помойку или нагло дурят нас.

Единственное, о чем можно с уверенностью говорить, что вот этот, конкретный исходник, откомпилированный вот этим конкретным компилятором, этой конкретной версии, из IDE или из командной строки конкретно, на этой конкретной машине, выполняется за это конкретное время. А тем компилятором - за то. Больше - ни о чём.

Потому, что для правильного процессора не имеет значение место расположения конкретных переменных в оперативной памяти и их величины. А для x86 - имеет. x86 - отстой и брак.

И поэтому, компилятор x86, который оказался наихудшим в предыдущем тесте, в следующем может оказаться наилучшим - случайно, не туда переменную тыкнул.

Для разных моделей x86, конечные результаты сравнительных тестов готовых программ на скорость, для разных компиляторов, не совпадают. На одной модели x86 выигрывает один компилятор, на другой - другой, с одним и тем же, неизменным, готовым кодом типа 2+2. Это полностью сбивает с толку кого угодно. Особенно, если компилятору запрещена любая оптимизация. Могу продемонстрировать, если надо. Так, вопреки всем ожиданиям, LCC32 может выиграть у Fasm 10%-15% скорости на полностью идентичном конечном коде. Кто из вас сможет это здраво себе объяснить?

Самого лучшего компилятора x86 не существует! Каким пользоваться? - зависит от личных предпочтений и каждый решает для себя сам.

Хотя, нет правил без исключений?

;Programm Speed.pb for PureBasic

;(c) Oleg E. Tereshkov 2014

;========================

Import "kernel32.lib"

GetTickCount()

EndImport

;========================

OpenConsole()

L1:

temp11.l = 1

temp12.l = 5

temp13.l = 1

temp14.l = 4

temp15.l = 2

temp16.l = 3

temp17.l = 4

temp18.l = 2

temp19.l = 5

temp20.l = 3

temp21.l = 2

temp1.l = 2147483647

temp2.l = 2147483647

temp3.l = 2147483647

temp4.l = 2147483647

temp5.l = 2147483647

temp6.l = 2147483647

temp7.l = 2147483647

temp8.l = 2147483647

temp9.l = 2147483647

temp10.l= 2147483647

temp0.l =GetTickCount()

While temp10>0

temp1=temp1 - temp11

temp2=temp2 - temp12

temp3=temp3 - temp13

temp4=temp4 - temp14

temp5=temp5 - temp15

temp6=temp6 - temp16

temp7=temp7 - temp17

temp8=temp8 - temp18

temp9=temp9 - temp19

temp10=temp10 - temp20

temp21=temp11

temp11=temp12

temp12=temp13

temp13=temp14

temp14=temp15

temp15=temp16

temp16=temp17

temp17=temp18

temp18=temp19

temp19=temp20

temp20=temp21

Wend

temp1=GetTickCount()

temp1=temp1 - temp0

PrintN(Str(temp1))

Goto L1

Время выполнения для PureBasic 4.10 - 22000мс, а для PureBasic 4.41 demo - 13500мс. Разница есть. Хоть и стоили оба эти компилятора одинаково. И дело тут, видимо, не только в порядке следования переменных. И именно поэтому, на сайте PureBasic, вы никогда не увидите предыдущих версий программы. Сами понимаете, грязное бельё, сор в избе и всё такое. Всё познаётся в сравнении и всё рано или поздно познаётся, даже человеческий геном и баги x86.

Исключения лишь подтверждают правило. И если компилятор не тупит так же откровенно, как PureBasic 3.20 - 4.10, GCC, Ionic, Easm и прочие тарахтелки, то быстродействие конечной программы для x86, при отсутствии грубых просчётов внутри её самой, во многом вопрос личного везения программиста и чистой случайности при объявлении переменных в исходнике.

Или вот, для SPHINX C-- 0.239 :

//speed.c--

#pragma option W32C

#pragma option J0

#pragma option 3

//-------------------

extern WINAPI "crtdll.dll"

{ printf();}

extern WINAPI "kernel32.dll"

{ GetTickCount();}

//-------------------

int temp0,temp1,temp2,temp3,\

temp4,temp5,temp6,temp7,\

temp8,temp9,temp10,temp11,\

temp12,temp13,temp14,temp15,\

temp16,temp17,temp18,temp19,\

temp20,temp21;

//----------------------------------

//-------------MAIN-----------------

//----------------------------------

int main (void){

L1: temp11=1;temp12=5;temp13=1;

temp14=4;temp15=2;temp16=3;

temp17=4;temp18=2;temp19=5;

temp20=3;temp21=2;

temp1=temp2=temp3=temp4=\

temp5=temp6=temp7=temp8=\

temp9=temp10 = 0x7fffffff;

temp0=GetTickCount();

while (temp10 > 0) {

temp1=temp1 - temp11;

temp2=temp2 - temp12;

temp3=temp3 - temp13;

temp4=temp4 - temp14;

temp5=temp5 - temp15;

temp6=temp6 - temp16;

temp7=temp7 - temp17;

temp8=temp8 - temp18;

temp9=temp9 - temp19;

temp10=temp10 - temp20;

temp21=temp20;temp20=temp19;

temp19=temp18;temp18=temp17;

temp17=temp16;temp16=temp15;

temp15=temp14;temp14=temp13;

temp13=temp12;temp12=temp11;

temp11=temp21; }

temp1=GetTickCount();

temp1=temp1 - temp0;

printf("%d\n", temp1);

goto L1;

}

Время выполнения 12500мс - самое быстрое, но если строчки "extern WINAPI "crtdll.dll" { printf();}" заменить на "extern WINAPI "crtdll.dll" {cdecl int printf(char *,...);}, как это и должно быть, время выполнения сразу увеличится до 13000мс, а это +4%, хоть ничего по сути и не изменилось. А если, для данного примера, кроме {int cdecl printf(char *,...);}, ещё и все переменные преобразовать в локальные, то время выполнения увеличится ещё больше и составит 13400мс, +7,2% от первоначальных 12500. Лохотрон от INTEL и AMD!

И можете оптимизировать и сравнивать сколько угодно. Увы, все нормальные компиляторы одинаковы, чтобы вам по этому поводу ни говорили и что бы вам лично самим ни казалось. И во всяких там ду-вайл и фо-нэкст, для x86, лучше использовать именно глобальные переменные. Быстрее будет. Вроде бы. Но не торопитесь с выводами.

О сколько нам открытий чудных готовит просвещенья дух!!!

Да, правда, а сколько нам ещё отвратительных открытий приготовили INTEL и AMD?

На заре цивилизации, гремел доспехами некий CPL32 и его младший брат ASM32. Их и сегодня хотят продавать по $30 за штуку. Под Виндой, они до сих пор не работают - держат марку, только под MSDOS - так, наверное, покупателей больше и лучше продаётся, но вот, как анонсируют эти поделки сами авторы: - CPL32, the best assembler for true, pure assembly programmers, there is absolutely NO RED TAPE, you do NOT declare variable types, segments or procedures.

Короче, программировать теперь можно по наитию, так, как бык по дороге посцал. Но хорошо ли это? Можно ли, таким образом стать к Богу ближе, чем римский папа, а к x86, ближе, чем INTEL и AMD?

FASM тоже, позволяет писать без всяких правил. А давайте-ка, перепишем второй листинг вот так:

;Programm Speed_me_2.asm for Fasm

;(c) Oleg E. Tereshkov 2015

;//-------------macro-------------//

macro library [label,string]

{ forward

local _label

dd 0,0,0,rva _label,rva label

common

dd 0,0,0,0,0

forward

_label db string,0 }

macro import [label,string]

{ forward

local _label

label dd rva _label

common

dd 0

forward

_label dw 0

db string,0 }

;//------------endmac-------------//

format PE console

entry start

start: nop

lbl0: mov eax, 7fffffffh

mov [temp1], eax

mov [temp2], eax

mov [temp3], eax

mov [temp4], eax

mov [temp5], eax

mov [temp6], eax

mov [temp7], eax

mov [temp8], eax

mov [temp9], eax

mov [temp10], eax

call [clock]

mov [temp0], eax

lbl1: cmp [temp10], 0

jle lbl2

mov eax,[temp1]

sub eax, [temp11]

mov [temp1], eax

mov ecx,[temp2]

sub ecx, [temp12]

mov [temp2], ecx

mov edx,[temp3]

sub edx, [temp13]

mov [temp3], edx

mov eax,[temp4]

sub eax, [temp14]

mov [temp4], eax

mov ecx,[temp5]

sub ecx, [temp15]

mov [temp5], ecx

mov edx,[temp6]

sub edx, [temp16]

mov [temp6], edx

mov eax,[temp7]

sub eax, [temp17]

mov [temp7], eax

mov ecx,[temp8]

sub ecx, [temp18]

mov [temp8], ecx

mov edx,[temp9]

sub edx, [temp19]

mov [temp9], edx

mov eax,[temp10]

sub eax, [temp20]

mov [temp10], eax

mov eax,[temp20]

mov [temp21], eax

mov ebx,[temp19]

mov [temp20], ebx

mov edx,[temp18]

mov [temp19], edx

mov ecx,[temp17]

mov [temp18], ecx

mov eax,[temp16]

mov [temp17], eax

mov ebx,[temp15]

mov [temp16], ebx

mov edx,[temp14]

mov [temp15], edx

mov ecx,[temp13]

mov [temp14], ecx

mov eax,[temp12]

mov [temp13], eax

mov ebx,[temp11]

mov [temp12], ebx

mov edx,[temp21]

mov [temp11], edx

jmp lbl1

lbl2: call [clock]

sub eax, [temp0]

push eax

push temp_s

call [printf]

add esp, 8

jmp lbl0

temp0 dd 0h

temp1 dd 0h

temp2 dd 0h

temp3 dd 0h

temp4 dd 0h

temp5 dd 0h

temp6 dd 0h

temp7 dd 0h

temp8 dd 0h

temp9 dd 0h

temp10 dd 0h

temp11 dd 3

temp12 dd 3

temp13 dd 3

temp14 dd 3

temp15 dd 3

temp16 dd 3

temp17 dd 3

temp18 dd 3

temp19 dd 3

temp20 dd 3

temp21 dd 3

temp_s db 25h,64h,0ah,0

;//-------------idata-------------//

section '.idata' import data readable writeable

library crtdll, 'crtdll.dll'

crtdll:

import printf,'printf',\

clock, 'clock'

Компилируем, запускаем. И опаньки - время выполнения сразу увеличивается в пять раз с 13350мс до 60200мс. Не хило! А казалось бы...

А что делать? Flat memory! Память у x86, она конечно ровная, но, как видно, не для всех, не для всего, не всегда и не во всех местах. Писать самомодифицирующийся код под x86 прикольно, но дебильно. Дебилизм!

Так какой же всё-таки компилятор выдаёт самый быстрый код - Fasm или Fasm же??? Что лучше??? Fasm или Fasm же??? Ведь, как вы сами видите, разница в скорости выполнения, одного и того же исходного кода, обработанного одним и тем же компилятором Fasm, при одних и тех же условиях, на одном и том же процессоре x86, может быть в пять раз!!!

----------------линия+отреза_2---------------

То были цветочки и предпосылки. Хотя, 5 раз - не такие уж и цветочки, но +400%. А теперь - ягодки и новые доказательства, серебряный гвоздь в сердце x86. Давайте дополним исходный код возможностью отображать ещё и количество тактов, отработанных процессором за тоже время, а заодно и избавимся от становящегося ненужным подсчёта миллисекунд, ну, для чистоты эксперимента, так сказать:

;Programm Speed_me_3.asm for Fasm

;(c) Tereshkov Oleg Evg. 2014

macro library [label,string]

{ forward

local _label

dd 0,0,0,rva _label,rva label

common

dd 0,0,0,0,0

forward

_label db string,0 }

macro import [label,string]

{ forward

local _label

label dd rva _label

common

dd 0

forward

_label dw 0

db string,0 }

format PE console

entry start

;//-------------code-------------//

section '.code' code readable executable

start: nop

lbl0: mov eax, 7fffffffh

mov [temp1], eax

mov [temp2], eax

mov [temp3], eax

mov [temp4], eax

mov [temp5], eax

mov [temp6], eax

mov [temp7], eax

mov [temp8], eax

mov [temp9], eax

mov [temp10], eax

rdtsc

mov [vr_temp_edx_1],edx

mov [vr_temp_eax_1],eax

lbl1: cmp [temp10], 0

jle lbl2

mov eax,[temp1]

sub eax, [temp11]

mov [temp1], eax

mov ecx,[temp2]

sub ecx, [temp12]

mov [temp2], ecx

mov edx,[temp3]

sub edx, [temp13]

mov [temp3], edx

mov eax,[temp4]

sub eax, [temp14]

mov [temp4], eax

mov ecx,[temp5]

sub ecx, [temp15]

mov [temp5], ecx

mov edx,[temp6]

sub edx, [temp16]

mov [temp6], edx

mov eax,[temp7]

sub eax, [temp17]

mov [temp7], eax

mov ecx,[temp8]

sub ecx, [temp18]

mov [temp8], ecx

mov edx,[temp9]

sub edx, [temp19]

mov [temp9], edx

mov eax,[temp10]

sub eax, [temp20]

mov [temp10], eax

mov eax,[temp11]

mov [temp21], eax

mov ebx,[temp12]

mov [temp11], ebx

mov edx,[temp13]

mov [temp12], edx

mov ecx,[temp14]

mov [temp13], ecx

mov eax,[temp15]

mov [temp14], eax

mov ebx,[temp16]

mov [temp15], ebx

mov edx,[temp17]

mov [temp16], edx

mov ecx,[temp18]

mov [temp17], ecx

mov eax,[temp19]

mov [temp18], eax

mov ebx,[temp20]

mov [temp19], ebx

mov edx,[temp21]

mov [temp20], edx

jmp lbl1

lbl2: rdtsc

sub eax,[vr_temp_eax_1]

jae sb1

neg eax

sb1: sbb edx,[vr_temp_edx_1]

mov [vr_temp_edx_2],edx

mov [vr_temp_eax_2],eax

mov eax,edx

call htd

mov eax,[vr_temp_eax_2]

call htd

call prp_d

mov [vr_temp_dec_3],eax

call prp_d

mov [vr_temp_dec_2],eax

call prp_d

mov [vr_temp_dec_1],eax

call prp_d

mov [vr_temp_eax_2],eax

call prp_d

mov [vr_temp_edx_2],eax

mov ebx,vr_temp_edx_2

fnd0: mov eax,[ebx]

cmp al,30h

jnz fnd0_2

inc ebx

jmp fnd0

fnd0_2: push ebx

call [printf]

add esp, 4

jmp lbl0

prp_d: pop ebx

pop edx

mov ah,dl

pop edx

mov al,dl

rol eax,16

pop edx

mov ah,dl

pop edx

mov al,dl

push ebx

ret

;=========--------------------->

htd: pop edx

xor ebx,ebx

htd1: sub eax,3B9ACA00h

jb htd1_2

inc ebx

je htd1_3

jmp htd1

htd1_2: add eax,3B9ACA00h

htd1_3: add ebx,030h

push ebx

xor ebx,ebx

htd2: sub eax,5F5E100h

jb htd2_2

inc ebx

je htd2_3

jmp htd2

htd2_2: add eax,5F5E100h

htd2_3: add ebx,030h

push ebx

xor ebx,ebx

htd3: sub eax,989680h

jb htd3_2

inc ebx

je htd3_3

jmp htd3

htd3_2: add eax,989680h

htd3_3: add ebx,030h

push ebx

xor ebx,ebx

htd4: sub eax,0F4240h

jb htd4_2

inc ebx

je htd4_3

jmp htd4

htd4_2: add eax,0F4240h

htd4_3: add ebx,030h

push ebx

xor ebx,ebx

htd5: sub eax,186A0h

jb htd5_2

inc ebx

je htd5_3

jmp htd5

htd5_2: add eax,186A0h

htd5_3: add ebx,030h

push ebx

xor ebx,ebx

htd6: sub eax,2710h

jb htd6_2

inc ebx

je htd6_3

jmp htd6

htd6_2: add eax,2710h

htd6_3: add ebx,030h

push ebx

xor ebx,ebx

htd7: sub eax,3E8h

jb htd7_2

inc ebx

je htd7_3

jmp htd7

htd7_2: add eax,3E8h

htd7_3: add ebx,030h

push ebx

xor ebx,ebx

htd8: sub eax,64h

jb htd8_2

inc ebx

je htd8_3

jmp htd8

htd8_2: add eax,64h

htd8_3: add ebx,030h

push ebx

xor ebx,ebx

htd9: sub eax,0Ah

jb htd9_2

inc ebx

je htd9_3

jmp htd9

htd9_2: add eax,0Ah

htd9_3: add ebx,030h

push ebx

mov ebx,eax

add ebx,030h

push ebx

push edx

ret

;//-------------idata-------------//

section '.idata' import data readable writeable

library crtdll, 'crtdll.dll'

crtdll:

import printf,'printf'

;//-------------data-------------//

section '.data' data readable writeable

temp0 dd 0h

temp1 dd 0h

temp2 dd 0h

temp3 dd 0h

temp4 dd 0h

temp5 dd 0h

temp6 dd 0h

temp7 dd 0h

temp8 dd 0h

temp9 dd 0h

temp10 dd 0h

temp11 dd 1

temp12 dd 5

temp13 dd 1

temp14 dd 4

temp15 dd 2

temp16 dd 3

temp17 dd 4

temp18 dd 2

temp19 dd 5

temp20 dd 3

temp21 dd 2

vr_temp_edx_0 dd 0h

vr_temp_eax_0 dd 0h

vr_temp_edx_1 dd 0h

vr_temp_eax_1 dd 0h

vr_temp_edx_2 dd 0h

vr_temp_eax_2 dd 0h

vr_temp_dec_1 dd 0h

vr_temp_dec_2 dd 0h

vr_temp_dec_3 dd 0h

vr_temp_dec_4 db 00ah,000h

vr_temp_ebx_1 dd 0h

vr_temp_esp_1 dd 0h

Зашуршало? Как эта погорамма работает, сейчас не важно. Я и сам уже не знаю, типа. Важно то, что она является полным аналогом двух предыдущих и выполняется за 50600000000 тактов процессора. А теперь давайте просто перепишем секцию .data вот таким образом:

;//-------------data-------------//

section '.data' data readable writeable

vr_temp_edx_0 dd 0h

vr_temp_eax_0 dd 0h

vr_temp_edx_1 dd 0h

vr_temp_eax_1 dd 0h

vr_temp_edx_2 dd 0h

vr_temp_eax_2 dd 0h

vr_temp_dec_1 dd 0h

vr_temp_dec_2 dd 0h

vr_temp_dec_3 dd 0h

vr_temp_dec_4 db 00ah,000h

vr_temp_ebx_1 dd 0h

vr_temp_esp_1 dd 0h

temp0 dd 0h

temp1 dd 0h

temp2 dd 0h

temp3 dd 0h

temp4 dd 0h

temp5 dd 0h

temp6 dd 0h

temp7 dd 0h

temp8 dd 0h

temp9 dd 0h

temp10 dd 0h

temp11 dd 1

temp12 dd 5

temp13 dd 1

temp14 dd 4

temp15 dd 2

temp16 dd 3

temp17 dd 4

temp18 dd 2

temp19 dd 5

temp20 dd 3

temp21 dd 2

Опаньки! А вот и оно! Снова! Время выполнения программы увеличилось в 5 раз, а количество потребных для этого тактов процессора составило аж целых 260500000000. Не хило!

----------------линия+отреза_3---------------

Слышу, слышу запоздалые крики прозрения: - Это всё Винда, это всё тупая Винда! Да нет, не Винда. И не Fasm. Это x86 такой. Вот аналог для MSDOS, а если надо могу выложить и для DiceRTE - http://www.diefer.de. И для DEXOS. Одно и тоже.

; Simple Speed5 demo, for MSDOS. Fasm

;(c) Oleg E. Tereshkov 2014

format binary as 'com'

use16

ORG 0x0000100

lbl0: mov eax, 7fffffffh

mov [temp1], eax

mov [temp2], eax

mov [temp3], eax

mov [temp4], eax

mov [temp5], eax

mov [temp6], eax

mov [temp7], eax

mov [temp8], eax

mov [temp9], eax

mov [temp10], eax

rdtsc

mov [vr_temp_edx_1],edx

mov [vr_temp_eax_1],eax

;=========--------------------->

lbl1: cmp [temp10], 0

jle lbl2

mov eax,[temp1]

sub eax, [temp11]

mov [temp1], eax

mov ecx,[temp2]

sub ecx, [temp12]

mov [temp2], ecx

mov edx,[temp3]

sub edx, [temp13]

mov [temp3], edx

mov eax,[temp4]

sub eax, [temp14]

mov [temp4], eax

mov ecx,[temp5]

sub ecx, [temp15]

mov [temp5], ecx

mov edx,[temp6]

sub edx, [temp16]

mov [temp6], edx

mov eax,[temp7]

sub eax, [temp17]

mov [temp7], eax

mov ecx,[temp8]

sub ecx, [temp18]

mov [temp8], ecx

mov edx,[temp9]

sub edx, [temp19]

mov [temp9], edx

mov eax,[temp10]

sub eax, [temp20]

mov [temp10], eax

mov eax,[temp11]

mov [temp21], eax

mov ebx,[temp12]

mov [temp11], ebx

mov edx,[temp13]

mov [temp12], edx

mov ecx,[temp14]

mov [temp13], ecx

mov eax,[temp15]

mov [temp14], eax

mov ebx,[temp16]

mov [temp15], ebx

mov edx,[temp17]

mov [temp16], edx

mov ecx,[temp18]

mov [temp17], ecx

mov eax,[temp19]

mov [temp18], eax

mov ebx,[temp20]

mov [temp19], ebx

mov edx,[temp21]

mov [temp20], edx

jmp lbl1

;=========---------------------->

lbl2: rdtsc

sub eax,[vr_temp_eax_1]

jae sb1

neg eax

sb1: sbb edx,[vr_temp_edx_1]

mov [vr_temp_edx_2],edx

mov [vr_temp_eax_2],eax

mov eax,edx

call htd

mov eax,[vr_temp_eax_2]

call htd

call prp_d

mov [vr_temp_dec_3],eax

call prp_d

mov [vr_temp_dec_2],eax

call prp_d

mov [vr_temp_dec_1],eax

call prp_d

mov [vr_temp_eax_2],eax

call prp_d

mov [vr_temp_edx_2],eax

mov ebx,vr_temp_edx_2

fnd0: mov eax,[ebx]

cmp al,30h

jnz fnd0_2

inc ebx

jmp fnd0

fnd0_2: mov dx,bx

mov ah,0x09

int 21h

push lbl0

ret

prp_d: pop ebx

pop edx

mov ah,dl

pop edx

mov al,dl

rol eax,16

pop edx

mov ah,dl

pop edx

mov al,dl

push ebx

ret

;=========------------------>

htd: pop edx

xor ebx,ebx

htd1: sub eax,3B9ACA00h

jb htd1_2

inc ebx

jmp htd1

htd1_2: add eax,3B9ACA00h

add ebx,030h

push ebx

xor ebx,ebx

htd2: sub eax,5F5E100h

jb htd2_2

inc ebx

jmp htd2

htd2_2: add eax,5F5E100h

add ebx,030h

push ebx

xor ebx,ebx

htd3: sub eax,989680h

jb htd3_2

inc ebx

jmp htd3

htd3_2: add eax,989680h

add ebx,030h

push ebx

xor ebx,ebx

htd4: sub eax,0F4240h

jb htd4_2

inc ebx

jmp htd4

htd4_2: add eax,0F4240h

add ebx,030h

push ebx

xor ebx,ebx

htd5: sub eax,186A0h

jb htd5_2

inc ebx

jmp htd5

htd5_2: add eax,186A0h

add ebx,030h

push ebx

xor ebx,ebx

htd6: sub eax,2710h

jb htd6_2

inc ebx

jmp htd6

htd6_2: add eax,2710h

add ebx,030h

push ebx

xor ebx,ebx

htd7: sub eax,3E8h

jb htd7_2

inc ebx

jmp htd7

htd7_2: add eax,3E8h

add ebx,030h

push ebx

xor ebx,ebx

htd8: sub eax,64h

jb htd8_2

inc ebx

jmp htd8

htd8_2: add eax,64h

add ebx,030h

push ebx

xor ebx,ebx

htd9: sub eax,0Ah

jb htd9_2

inc ebx

jmp htd9

htd9_2: add eax,0Ah

add ebx,030h

push ebx

mov ebx,eax

add ebx,030h

push ebx

push edx

ret

;=========---data1-------->

temp0 dd 0h

temp1 dd 0h

temp2 dd 0h

temp3 dd 0h

temp4 dd 0h

temp5 dd 0h

temp6 dd 0h

temp7 dd 0h

temp8 dd 0h

temp9 dd 0h

temp10 dd 0h

temp11 dd 1

temp12 dd 5

temp13 dd 1

temp14 dd 4

temp15 dd 2

temp16 dd 3

temp17 dd 4

temp18 dd 2

temp19 dd 5

temp20 dd 3

temp21 dd 2

vr_temp_edx_0 dd 0h

vr_temp_eax_0 dd 0h

vr_temp_edx_1 dd 0h

vr_temp_eax_1 dd 0h

vr_temp_edx_2 dd 0h

vr_temp_eax_2 dd 0h

vr_temp_dec_1 dd 0h

vr_temp_dec_2 dd 0h

vr_temp_dec_3 dd 0h

vr_temp_dec_4 db 00ah,'$'

vr_temp_ebx_1 dd 0h

vr_temp_esp_1 dd 0h

Компилируем, запускаем под Виндовс - чуть медленнее оригинала. А под чистым досом - ещё медленнее. Теперь перепишем секцию data, такова традиция.

;=========---data2-------->

vr_temp_edx_0 dd 0h

vr_temp_eax_0 dd 0h

vr_temp_edx_1 dd 0h

vr_temp_eax_1 dd 0h

vr_temp_edx_2 dd 0h

vr_temp_eax_2 dd 0h

vr_temp_dec_1 dd 0h

vr_temp_dec_2 dd 0h

vr_temp_dec_3 dd 0h

vr_temp_dec_4 db 00ah,'$'

vr_temp_ebx_1 dd 0h

vr_temp_esp_1 dd 0h

temp0 dd 0h

temp1 dd 0h

temp2 dd 0h

temp3 dd 0h

temp4 dd 0h

temp5 dd 0h

temp6 dd 0h

temp7 dd 0h

temp8 dd 0h

temp9 dd 0h

temp10 dd 0h

temp11 dd 1

temp12 dd 5

temp13 dd 1

temp14 dd 4

temp15 dd 2

temp16 dd 3

temp17 dd 4

temp18 dd 2

temp19 dd 5

temp20 dd 3

temp21 dd 2

И снова, время выполнения программы увеличилось в 5 раз. Теперь вернёмся к первоначальному варианту, но в начале добавим ничего не значащую строчку, которая в программе нигде не используется.

;=========---data3-------->

hllspd db "Hello! I'm Speedy speedometr !!!",00ah,00ah,000h

temp0 dd 0h

temp1 dd 0h

temp2 dd 0h

temp3 dd 0h

temp4 dd 0h

temp5 dd 0h

temp6 dd 0h

temp7 dd 0h

temp8 dd 0h

temp9 dd 0h

temp10 dd 0h

temp11 dd 1

temp12 dd 5

temp13 dd 1

temp14 dd 4

temp15 dd 2

temp16 dd 3

temp17 dd 4

temp18 dd 2

temp19 dd 5

temp20 dd 3

temp21 dd 2

vr_temp_edx_0 dd 0h

vr_temp_eax_0 dd 0h

vr_temp_edx_1 dd 0h

vr_temp_eax_1 dd 0h

vr_temp_edx_2 dd 0h

vr_temp_eax_2 dd 0h

vr_temp_dec_1 dd 0h

vr_temp_dec_2 dd 0h

vr_temp_dec_3 dd 0h

vr_temp_dec_4 db 00ah,'$'

vr_temp_ebx_1 dd 0h

vr_temp_esp_1 dd 0h

И снова, время выполнения программы увеличилось в 5 раз. Лично я не взялся бы утверждать, так какое же время правильное. Знаю только, что так не должно быть. Но всё равно, я всех поздравляю, особенно тех, кто купил QNX. Всё это как-то мало похоже на real time. Деньги потрачены, а в итоге - шиш. Фигня она и есть фигня, фигнёй и останется - x86.

Конечно, после того, как вонь разнесётся по миру INTEL и AMD нам всё объяснит. Может даже выяснится, что так и должно быть, что так и надо, что это хитрость такая, против хакеров, чтобы пароли перебором не ломали.

Но лично я предпочёл бы получить деньги обратно, хоть к x86 и привык. Не знаю пойдут ли теперь акции INTEL и AMD вверх или упадут, но я бы на месте I&A в феврале эту статью купил и вы бы сейчас её не читали. Но что сделано, то сделано. А как на месте INTEL и AMD поступили бы вы? А что по этому поводу думают их главные акционеры? - Ничего личного, только бизнес?

----------------линия+отреза_4---------------

Вот ещё программка:

; MHZ.asm for Fasm

;(c) Tereshkov Oleg Evg. 2014

macro library [label,string]

{ forward

local _label

dd 0,0,0,rva _label,rva label

common

dd 0,0,0,0,0

forward

_label db string,0 }

macro import [label,string]

{ forward

local _label

label dd rva _label

common

dd 0

forward

_label dw 0

db string,0 }

format PE console

entry start

;=========----------------------------------------->

section '.code' code readable executable

start: nop

lbl0: rdtsc

mov [vr_temp_edx_1],edx

mov [vr_temp_eax_1],eax

;=========----------------------------------------->

lbl1:

call [clock]

mov [temp0], eax

push 1000d

call [Sleep]

;=========----------------------------------------->

lbl2: call [clock]

sub eax, [temp0]

push eax

push temp_s

call [printf]

add esp, 8

rdtsc

sub eax,[vr_temp_eax_1]

jae sb1

neg eax

sb1: sbb edx,[vr_temp_edx_1]

mov [vr_temp_edx_2],edx

mov [vr_temp_eax_2],eax

mov eax,edx

call htd

mov eax,[vr_temp_eax_2]

call htd

call prp_d

mov [vr_temp_dec_3],eax

call prp_d

mov [vr_temp_dec_2],eax

call prp_d

mov [vr_temp_dec_1],eax

call prp_d

mov [vr_temp_eax_2],eax

call prp_d

mov [vr_temp_edx_2],eax

mov ebx,vr_temp_edx_2

fnd0: mov eax,[ebx]

cmp al,30h

jnz fnd0_2

inc ebx

jmp fnd0

fnd0_2: push ebx

call [printf]

add esp, 4

jmp lbl0

prp_d: pop ebx

pop edx

mov ah,dl

pop edx

mov al,dl

rol eax,16

pop edx

mov ah,dl

pop edx

mov al,dl

push ebx

ret

;=========----------------------------------------->

htd: pop edx

xor ebx,ebx

htd1: sub eax,3B9ACA00h

jb htd1_2

inc ebx

je htd1_3

jmp htd1

htd1_2: add eax,3B9ACA00h

htd1_3: add ebx,030h

push ebx

xor ebx,ebx

htd2: sub eax,5F5E100h

jb htd2_2

inc ebx

je htd2_3

jmp htd2

htd2_2: add eax,5F5E100h

htd2_3: add ebx,030h

push ebx

xor ebx,ebx

htd3: sub eax,989680h

jb htd3_2

inc ebx

je htd3_3

jmp htd3

htd3_2: add eax,989680h

htd3_3: add ebx,030h

push ebx

xor ebx,ebx

htd4: sub eax,0F4240h

jb htd4_2

inc ebx

je htd4_3

jmp htd4

htd4_2: add eax,0F4240h

htd4_3: add ebx,030h

push ebx

xor ebx,ebx

htd5: sub eax,186A0h

jb htd5_2

inc ebx

je htd5_3

jmp htd5

htd5_2: add eax,186A0h

htd5_3: add ebx,030h

push ebx

xor ebx,ebx

htd6: sub eax,2710h

jb htd6_2

inc ebx

je htd6_3

jmp htd6

htd6_2: add eax,2710h

htd6_3: add ebx,030h

push ebx

xor ebx,ebx

htd7: sub eax,3E8h

jb htd7_2

inc ebx

je htd7_3

jmp htd7

htd7_2: add eax,3E8h

htd7_3: add ebx,030h

push ebx

xor ebx,ebx

htd8: sub eax,64h

jb htd8_2

inc ebx

je htd8_3

jmp htd8

htd8_2: add eax,64h

htd8_3: add ebx,030h

push ebx

xor ebx,ebx

htd9: sub eax,0Ah

jb htd9_2

inc ebx

je htd9_3

jmp htd9

htd9_2: add eax,0Ah

htd9_3: add ebx,030h

push ebx

mov ebx,eax

add ebx,030h

push ebx

push edx

ret

;=========----------------------------------------->

;//-------------idata-------------//

section '.idata' import data readable writeable

library Msvcrt,'Msvcrt.dll',\

kernel32,'kernel32.dll'

Msvcrt:

import printf,'printf',\

clock, 'clock'

kernel32:

import Sleep,'Sleep'

;//-------------data-------------//

section '.data' data readable writeable

temp0 dd 0h

temp_s db 25h,64h,0ah,0

vr_temp_edx_0 dd 0h

vr_temp_eax_0 dd 0h

vr_temp_edx_1 dd 0h

vr_temp_eax_1 dd 0h

vr_temp_edx_2 dd 0h

vr_temp_eax_2 dd 0h

vr_temp_dec_1 dd 0h

vr_temp_dec_2 dd 0h

vr_temp_dec_3 dd 0h

vr_temp_dec_4 db 00ah,000h

vr_temp_ebx_1 dd 0h

vr_temp_esp_1 dd 0h

Она измеряет частоту работы процессора. У меня через раз вылетают два значения - 1833653534 и 2461100546, примерно. А у вас? И какое же из них верное? Чем докажешь? Взять среднее арифметическое за год? Ну, что ж - разумно.

----------------линия+отреза_5---------------

Выводы:

1. Мной, О.Е. Терешковым выявлен и доказан новый баг процессоров x86. Проявляющийся в непредсказуемом замедлении скорости работы и непредсказуемых выходных данных программ в зависимости от порядка расположения, следования и величины переменных в конечном коде и просто так, без всякой зависимости и причины, как таковой.

2. Ни одна сущность во Вселенной, включая божественную, и ни одна #лядь на Земле не знает, что же внутри x86, на самом деле, происходит.

3. Один risc на два действия с тремя десятками внутренних регистров лучше, чем все Intel/AMD вместе взятые. risc детерминирован и предсказуем. Intel/AMD - мрак и дремучий лес.

4. Давать роботам возможность хоть как-то влиять на человеческую жизнь - верх глупости, идиотизма, жестокости и бесчеловечности. Кто поступает так - нелюдь. Вспомните авторегистраторы превышения скорости, засыпающие несчастных водителей бесконечными штрафами на пустом месте. Вот вам грядущее завтра человечества, когда железяке верят, а человеку - нет и не дают оправдаться.

Кучка кремния размером 5х5 мм - всё, благополучие человека - ничто. Подумайте только, безмозглая кучка кремния размером 5х5 мм выписывает вам штрафы! Полицаи к ней - только придаток. И вы подчиняетесь ей, идёте и платите. А вы же тогда кто? Человеки? Образы и подобия божьи? - Скот! Куры и коровы, которые должны доиться и нестись. Наверное, вы должны исчезнуть.

Человечество уже давно подписало себе смертный приговор. И называется он безисходность. Роботы уже давно управляют вами, обирают и долбят. Только и того, что пока не бьют вас ногами под дых. Хотя, как сказать. Но и это будущее уже не за горами. Скоро научатся. Терминатора помните? Строгайте доски, Шура. Зачем? Нынче в моде пластиковый пакет! Время предъявлять иски к Intel и AMD.

5. В свете вышеизложенного, абсолютной глупостью выглядят попытки сравнивать компиляторы x86 по быстродействию конечного кода программ. Такое сравнение - абсурд.

6. Производители синтетических тестов для x86 должны разориться. А AMD и Intel должны пойти на беспрецедентную замену всего их барахла, которое они успели продать-втюхать наивным дурачкам за последние 35 лет, начиная с 1980 года.

7. Это открытие не имеет никакого значения для конкретного пользователя, просто ползающего по интернету. Какая разница, откроется браузер за 1/2000000000 или за 5/2000000000 секунды? И блокнот и рисовалка будут и дальше прекрасно работать.

8. Это открытие имеет огромное значение для институтов и университетов проводящих научные исследования на x86, если таковые вообще есть. Есть большая разница: будут результаты получены через год или через пять, через десять лет или через пятьдесят. И будут ли они верными? Кто согласен столько ждать и платить за итоговую туфту?

9. Это открытие имеет огромное значение для работодателей, которые платят зарплату своим работникам, полирующим свои трубы пока их x86 тарахтят вхолостую. Время предъявлять иски к Intel и AMD.

10. Это открытие имеет огромное значение везде, где производится аудио-видео рендеринг - на аудио, кино, теле и радио студиях. Кому нужны сверхурочные?

11. Это открытие имеет огромное значение для РосКосмоса, с завидной регулярностью, топящего в Тихом океане свои носители. Наминуточку, а сколько x86 использует и он? А NASA, у которого спутники промахиваются мимо планет? Время предъявлять иски к Intel и AMD.

12. Я уже не говорю про брут форс взлом паролей на пятикратно замедленном процессоре - ещё одна сказочка для наивных дурачков.

13. С недавнего времени и Aple переполз на x86. Принимайте поздравления. Не даром вы отвалили столько за свой новый Мак! Опять видится прозорливость и гений Джобса. Как он вас! И ныне, и присно, и во веки веков.

14. Забудьте и подотритесь бесконечными километрами книг и научных статей, посвящённых оптимизации кода x86. x86 этих книг не читает. Я - О.Е. Терешков осветил вам путь и расшарил горизонты. В предложенной вам простейшей программе 22 числовые переменные. Наминуточку, кто из вас знает количество размещений из 22 по 22? Перебирать - не перебрать. И детям вашим и внукам хватит. Пора штаты тестеров расширять. И спецпрограммы автоматизации этого дела писать. Но учитывая вновь открывшуюся специфику x86, как бы ещё дольше не вышло.

15. Пора перестать плевать и гадить в сторону Виндовс. Создать промышленный стандарт на такой байдЕ, как x86 - высокое искусство. А что можете лично вы, плюющие по поводу и без?

16. Писать самомодифицирующийся код под x86 - самоубийство. Майкрософт, а потом и Linux, видимо, обо всём знал. О чём косвенно свидетельствует формат PE-файла, с отдельной секцией переменных .data. С самого начала, Intel и AMD, видимо, открыли Microsoft и Linux секрет, как именно выстраивать код и переменные в PE-файле, чтобы WINDOWS никогда не тормозила так безбожно, как всегда безбожно тормозит REACTOS. И как бы вы не изощрялись, ваша программа ни когда не будет работать так же быстро, как ntoskrnl.exe. И не потому, что вы тупые или кольцо 0, а потому, что с самого начала задумано так. Заманчивая перспектива! - Вы всегда второй сорт. А все заказы - у них. Бесчестная конкуренция, монополизм.

17. Учитывая, что баг присущ всем моделям x86, а также то, что x86 микрокомпьютер сам по себе, со своим внутренним процессором и микрокодом внутри, логично предположить наличие встроенного пароля-ключа. Если программа его предъявляет - работает быстро. Если нет - безбожно тормозит. 1.83/5=366Мгц для AMD Athlon(tm)XP 2500+ 1.83Ггц. Именно поэтому, почти все программы звукозаписи ни куда не годятся.

18. Видимо, именно из-за ключа-пароля к x86, Майкрософт, с самого начала Виндовс, навязывал всем VC++. Достаточно посмотреть на то, какой объёмный пролог-эпилог VC++ генерирует. Спрятать ключ-пароль в таком количестве ненужного и бессмысленного мусора - проще простого. Только с ключом от Microsoft программы будут летать, а с вашим - ползать, как дохлые черепахи. Именно поэтому, даже самые известные производители оборудования заказывают драйвера для своих устройств именно в Microsoft. Квалификацию они имеют, а ключ - нет. Вот их собственные драйвера никуда и не годятся. Понадобились усилия многих людей, чтобы вернуть Ассемблер в Виндовс. Благодаря ассемблеру и написана эта статья.

19. Вполне возможно, что существует вариант x86 для Пентагона и своих, лишённый описанной ошибки и варианты для всех остальных дурачков. Поздравляю. Вы лично из какого лагеря? И я.

20. Дерьмо(x86) - оно, и из Америки, дерьмо.

21. Данная статья была предложена на рецензию lisa.su@amd.com, andy.bryant@intel.com, brian.krzanich@intel.com, harry.wolin@amd.com, mark.papermaster@amd.com. Ни кто из них так и не оторвал свой зад от табуретки, и не промямлил ничего в ответ. Видимо за это, им и платят их миллионы. Если бы у них было чуть больше ума, вы бы сейчас эту статью не читали. А я - жил в Майями. Но где вы видели умного руководителя? Где? В Intel? В AMD? Как говорят в солнечной Украине: Маемо тэ щё маемо - что есть, то есть. Ешьте теперь. Не даром ведь, x86 такой.

22. Данная работа вполне тянет и на кандидатскую и на докторскую, и на нобелевскую. Но какая академия наук мне её даст? Науке, как и производству, нет дела до реальной жизни. Только бабло!

23. Кому это всё надо, если оно не работает так, как надо? INTEL и AMD, каждая шла своим долгим путём, а в итоге у каждой получился якобы свой процессор с абсолютно идентичными багами, как у "конкурента". Ну, и кого же вы хотели нае#ать?

24. Недавно, за $27, я купил DELL INSPIRON 510m c INTEL MOBILE 1.70GHz внутри. Но на 1.70GHz он работает 15-20 секунд на старте и сразу же переходит на 597MHz. Кто мне может сказать почему? DELL? INTEL?

25. Скажите ещё, что это вас опять инопланетяне подставили. Как на Луне. Тупые лохи. Адью.

PS. Ну, то, что российский журнал Хакер уже пролетел, это всем понятно. А вот для INTEL и AMD, всё остаётся в силе. Отцы-основатели, по прежнему могут приобрести права на копирование. По февральской цене. Не смотря на инфляцию.

Копирайт: (c) Oleg E. Tereshkov декабрь 2014. Данная статья является собственностью Oleg E. Tereshkov во всех смыслах. Любое её использование, тиражирование, копирование и воспроизводство - только после предоплаты и моего письменного согласия. Вполне в духе Microsoft, Intel и AMD.

Люблю вас всех! А теперь, идите и с верой и энтузиазмом программируйте на x86 новую, человеческую ДНК, меняйте человеческий геном. Вперёд!

Да, ну и конечно, вам всегда рады и в INTEL, и в AMD. Заходите. Поверьте. Я это знаю лучше всех.

Открытое письмо для Intel&Amd от 28 ноября 2015:

Привет, Intel&Amd. За истекшую неделю эту страницу https://sites.google.com/site/excelmidi/ просмотрело свыше семисот программистов со всего мира. Среди них такие известные, как Fred - PureBasic, hutch - Masm32, Tomasz Grysztar - Fasm, Jacob Navia - LCC32, Andrew Stuart Tanenbaum - Minix, Linus Benedict Torvalds - Linux, William Henry Gates - Windows. Возражений не возникло и всё подтвердилось.

Если это шутка, то она не смешная.

Мы потратили годы на обучение. Ещё годы, чтобы приобрести опыт. Мы много работаем, доводя наши программы до совершенства, чтобы предоставить пользователю максимальный комфорт и быстродействие.

Поэтому, новый сюрприз с размещением переменных, совершенно обескураживает и заставляет опустить руки. Обратно к секретным сегментным регистрам? Мы готовы. Ну так покажите их нам.

Мы ждём объяснений. Программисты всего мира.

Как иллюстрацию наших слов, приводим две простейшие, абсолютно идентичные программы

- quick.asm и slow.asm, разница в скорости выполнения которых составляет 94 раза для AMD Athlon (tm) XP 2500+ и 30 раз для Intel(R) Pentium(R) M.

И это не смешно.

Таким образом, если вы, будучи программистом, не можете дождаться результатов от своей программы - запасайтесь терпением. Сходите в кино, возьмите отпуск на неделю или переключитесь на другой проэкт. И результаты придут. Или просто поменяйте местами переменные.

Если у вас нет времени ждать, воспользуйтесь строкой lbl0: mov eax, 004f0000h

;Programm quick.asm for Fasm

;(c) Oleg E. Tereshkov 2015

format PE console

entry start

;//-------------macro-------------//

macro library [label,string]

{ forward

local _label

dd 0,0,0,rva _label,rva label

common

dd 0,0,0,0,0

forward

_label db string,0 }

macro import [label,string]

{ forward

local _label

label dd rva _label

common

dd 0

forward

_label dw 0

db string,0 }

;//------------endmac-------------//

;//-------------idata-------------//

section '.idata' import data readable writeable executable

library crtdll, 'crtdll.dll'

crtdll:

import printf,'printf',\

clock, 'clock'

;//-------------data-------------//

temp0 dd 0h

temp1 dd 0h

temp2 dd 0h

temp3 dd 0h

temp4 dd 0h

temp5 dd 0h

temp6 dd 0h

temp7 dd 0h

temp8 dd 0h

temp9 dd 0h

temp10 dd 0h

temp11 dd 3

temp_s db 25h,64h,0ah,0

;//-------------code-------------//

start: nop

lbl0: mov eax, 4f000000h

mov [temp1], eax

mov [temp2], eax

mov [temp3], eax

mov [temp4], eax

mov [temp5], eax

mov [temp6], eax

mov [temp7], eax

mov [temp8], eax

mov [temp9], eax

mov [temp10], eax

call [clock]

mov [temp0], eax

lbl1: mov eax,[temp1]

sub eax, [temp11]

mov [temp1], eax

mov ecx,[temp2]

sub ecx, [temp11]

mov [temp2], ecx

mov edx,[temp3]

sub edx, [temp11]

mov [temp3], edx

mov eax,[temp4]

sub eax, [temp11]

mov [temp4], eax

mov ecx,[temp5]

sub ecx, [temp11]

mov [temp5], ecx

mov edx,[temp6]

sub edx, [temp11]

mov [temp6], edx

mov eax,[temp7]

sub eax, [temp11]

mov [temp7], eax

mov ecx,[temp8]

sub ecx, [temp11]

mov [temp8], ecx

mov edx,[temp9]

sub edx, [temp11]

mov [temp9], edx

mov eax,[temp10]

sub eax, [temp11]

mov [temp10], eax

cmp eax, 00h

jg lbl1

call [clock]

sub eax, [temp0]

push eax

push temp_s

call [printf]

add esp, 8

jmp lbl0

;Programm slow.asm for Fasm

;(c) Oleg E. Tereshkov 2015

format PE console

entry start

;//-------------macro-------------//

macro library [label,string]

{ forward

local _label

dd 0,0,0,rva _label,rva label

common

dd 0,0,0,0,0

forward

_label db string,0 }

macro import [label,string]

{ forward

local _label

label dd rva _label

common

dd 0

forward

_label dw 0

db string,0 }

;//------------endmac-------------//

;//-------------idata-------------//

section '.idata' import data readable writeable executable

library crtdll, 'crtdll.dll'

crtdll:

import printf,'printf',\

clock, 'clock'

;//-------------code-------------//

start: nop

lbl0: mov eax, 4f000000h

mov [temp1], eax

mov [temp2], eax

mov [temp3], eax

mov [temp4], eax

mov [temp5], eax

mov [temp6], eax

mov [temp7], eax

mov [temp8], eax

mov [temp9], eax

mov [temp10], eax

call [clock]

mov [temp0], eax

lbl1: mov eax,[temp1]

sub eax, [temp11]

mov [temp1], eax

mov ecx,[temp2]

sub ecx, [temp11]

mov [temp2], ecx

mov edx,[temp3]

sub edx, [temp11]

mov [temp3], edx

mov eax,[temp4]

sub eax, [temp11]

mov [temp4], eax

mov ecx,[temp5]

sub ecx, [temp11]

mov [temp5], ecx

mov edx,[temp6]

sub edx, [temp11]

mov [temp6], edx

mov eax,[temp7]

sub eax, [temp11]

mov [temp7], eax

mov ecx,[temp8]

sub ecx, [temp11]

mov [temp8], ecx

mov edx,[temp9]

sub edx, [temp11]

mov [temp9], edx

mov eax,[temp10]

sub eax, [temp11]

mov [temp10], eax

cmp eax, 00h

jg lbl1

call [clock]

sub eax, [temp0]

push eax

push temp_s

call [printf]

add esp, 8

jmp lbl0

;//-------------data-------------//

temp0 dd 0h

temp1 dd 0h

temp2 dd 0h

temp3 dd 0h

temp4 dd 0h

temp5 dd 0h

temp6 dd 0h

temp7 dd 0h

temp8 dd 0h

temp9 dd 0h

temp10 dd 0h

temp11 dd 3

temp_s db 25h,64h,0ah,0

Дополнение от 13 июня 2016. За что боролись, на то и напоролись. Выдержка - оборотная сторона стремительности. Я специально взял полугодовую паузу, чтобы расставить все точки над Й.

Интел и АМД, как и следовало ожидать, хранят ледяное молчание. И будут хранить его всегда. Им нечего сказать. И тем более не хочется производить замену всего их, временами и не предсказуемо, мягко говоря, не очень производительного барахла, проданного за последние 26 лет.

Это со всей убедительностью доказывает, что ни Интел, ни АМД не владеют ситуацией, а обеспечивают только репродукцию и тираж. И шутка, по поводу производства x86 по кальке инопланетян, совсем даже и не шутка, а проза жизни.

Я естественно не сидел сложа руки, а между делом, как и планировал, успел поучаствовать в Bell Labs Prize. Команда Bell Labs Prize team, как и следовало ожидать в таких щекотливых обстоятельствах, предпочла отморозиться и вначале не увидела предложения в моем предложении совместно с Bell Labs исследовать описанную в этой статье проблему.

На моё справедливое и очень вежливое замечание, что в конце-концов нельзя же быть такими тупыми, Bell Labs Prize team собрала повторный консилиум и отказала мне, с формулировкой в том, что участие в конкурсе описанного здесь материала может нанести непоправимый вред будущему всей компьютерной индустрии.

Ну что же, за будущее всей компьютерной индустрии теперь можно быть спокойным. С таким классным процессором x86, оно не пропадёт. Но согласитесь, если это не Победа, то по крайней мере Признание.

Сама Bell Labs, пусть и не громко, тихо, стыдливо, официально, но в частном порядке признала существование нового бага x86. И даже вступилась за будущее всей компьютерной индустрии. Похвально.

Конечно, если бы я был не я, а какой-нибудь Кнут, Рич или Керниган, то возможно, всё было бы по другому. И Bell Labs снова трубила бы на всех перекрёстках о своих новых достижениях самой себя. А так -

Скажите-ка навскидку: в Европе и США живёт 400 млн. человек. В Индии и Китае - 3 млрд. А сколько Нобелевских лауреатов среди тех и других?

Конечно, времена Кернигана и Рич в Bell Labs давно прошли. И теперь, слава Bell Labs - люди типа Jan Hendrik Schon. Поэтому, как вы понимаете, связывать какие-либо надежды с Bell Labs, сегодня - просто глупо. Кстати, их OS Plan9 даже не загружается, вот уже в течении, наверное, последних 10-и лет. Забавно, не правда ли?

Ну и совсем детское предположение - Bell Labs и Bell Labs Prize финансируются Интел и АМД. В этом случае, как говориться, комментарии излишни.

И что же делать? Если это лето, собирать ягоды и варить из них варенье. Если зима, пить с этим вареньем чай. x86 не тянет на предмет культа. Если вы профи, попробуйте смириться и побороть в себе досаду и естественное разочарование. У вас нет выхода. Если вы любитель, относитесь к программированию, как к полезному развлечению, которое улучшает вас.

Чтобы наткнуться на этот баг, мне понадобилось 3 дня. Чтобы Интел и АМД признали его существование и объяснили хоть как-нибудь, понадобится 30000 лет. Относитесь к x86 также, как вы относитесь к рулончику туалетной бумаги, пачке сигарет или гигиеническим прокладкам. Т.е. так, как он того заслуживает - потребительски. И тогда, наконец, всё встанет на свои места.

Согласитесь, без компьютеров, жизнь была бы намного более серой, скучной, скотской и неинтересной, но зато более естественной, живой, спокойной и человеческой - до ста лет.

Вива Гугл, вива Интел и АМД, привет будущему всей компьютерной индустрии и успехов всем нам. Особая благодарность Маркусу из Bell Labs Prize team. Люблю тебя. Будущее, всей компьютерной индустрии, будет помнить тебя. Всегда!

Дополнение от 16.11.2017. Подарок, для всех тех, кто дочитал до этого места, но, в силу разных причин, не смог разобраться в предложенных примерах и сделать для себя правильные выводы. Intel и Amd, конечно подлецы. Но польза от статьи должна быть, верно? Поэтому:

Если вы хотите, чтобы ваша программа работала быстро, порядок

следования разделов в ней, в общем случае, должен быть только такой:

.code

(.import data (*.dll))

.data

Этого не знают даже многие авторы прославленных компиляторов и линкеров. Вы знаете. :) И конечно, никакой само модификации в критических блоках. :) x86 этого ой, как не любит. Бай!