Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2003.10.06;
Скачать: [xml.tar.bz2];

Вниз

---|Ветка была без названия|---   Найти похожие ветки 

 
Юрий Зотов   (2003-07-06 13:32) [0]

Идем дальше. Предыдущий этап находится здеcь:
http://delphimaster.net/view/14-1046809017/

Продолжаем изучать основы устройства и работы коипьютера, продолжаем осваивать основы низкоуровневого программирования. Используя все тот же MK, но сопоставляя его с ПК. Сейчас наша задача - закончить рассмотрение команд перехода и подойти кследующей (и ОЧЕНЬ важной!) теме - адресации.

Простейшую команду перехода (безусловный переход) мы уже рассматривали, а когда Вы писали программы решения уравнений, то при проверке числа на ноль наверняка использовали либо команду F X=0, либо противоположную ей F X‡0. Вот это уже команды УСЛОВНОГО перехода - "перейти по указанному адресу, если содержимое RX равно (или не равно) нулю". Кроме них, в МК существуют еще команды F X>=0 и F X<0, а в ПК набор подобных команд намного шире. Перечень команд условного перехода для процессора 8088 такой: JA/JNBE, JAE/JNB/JNC, JB/JNAE/JC, JBE/JNA, JCXZ, JE/JZ, JG/JNLE, JGE/JNL, JL/JNGE, JLE/JNG, JNE/JNZ, JNO, JNP/JPO, JNS, JO, JP/JPE, JS. Мнемоника этих команд довольно простая, например: J-jump (перейти), N-not (не), G-greater (больше), E-equal (равно), L-lesser (меньше), C-carry(перенос), Z-zero (ноль), O-overflow (переполнение), P-parity (четность), S-sign (знак). Скажем, JNGE означает "перейти, если не больше и не равно", JZ - "перейти, если ноль", а JNO - "перейти, если нет переполнения". Но дело, конечно, не в количестве команд и не в их названиях (все это мы всегда можем найти в справочнике), а в том, как они работают. Вот это нам и нужно понять.

Когда-то мы уже говорили о регистре флагов и о том, что в нем существуют флаги переноса (CF) и переполнения (OF). Помимо них, в этом регистре еще есть флаги нуля (ZF - устанавливается при нулевом результате выполнения команды), четности (PF - устанавливается, если младший байт этого результата содержит четное число единиц) и знака (SF - всегда равен старшему биту результата). Вот с этими флагами и работают команды безусловного перехода. Например, пусть содержимое регистра EAX равно FFFFFFFF и выполняется такой кусок программы:

INC EAX ; увеличить EAX на 1
JZ LBL ; если ноль, перейти на адрес, помеченный в программе идентификатором LBL

После выполнения первой команды EAX будет равно нулю и выставится флаг ZF. Вторая команда проверит этот флаг, увидит, что он выставлен - и произойдет переход по адресу LBL. Все просто. Примерно так же сработает и такой кусок:

SUB EBX, EAX ; вычесть EAX из EBX и записать результат в EBX
JNE LBL ; если не равно, перейти по адресу LBL

Если EAX и EBX были равны, то после выполнения первой команды выставится флаг ZF, и перехода по адресу LBL не будет. А если EAX и EBX не были равны, то после выполнения первой команды флаг ZF, наоборот, сбросится и переход будет выполнен.

Рассмотрим маленькую иллюстрацию, которая, к тому же, послужит вступлением к нашей следующей теме - адресации. Сделайте в Delphi новый проект, дважды кликните по пустой форме и в появившемся обработчике события OnCreate напишите вот что:

procedure TForm1.FormCreate(Sender: TObject);
var
I, J: Integer;
begin // Здесь поставьте BreakPoint
I := 4;
If I > 2 then J := 1 else J := 2;
end;

Теперь в меню Delphi выберите Project | Options, в диалоге на закладке Compiler снимите птичку Optimization и нажмите ОК. Далее поставьте точку останова (BreakPoint) на строке begin (для этого щелкните по ней на левом поле редактора) и запустите программу. После остановки на BreakPoint в меню Delphi выберите View | Debug Windows | CPU - и Вы увидите окно CPU с ассемблерным кодом нашей программы, а в нем примерно вот такой кусок:

0043E334 ... push ebp ; Это точка входа в наш обработчик OnCreate. Ее адрес - $43E334.
...
0043E340 ... mov [ebp-$08], $00000004 ; Это I := 4
0043E347 ... cmp dword ptr [ebp-$08], $02 ; Сравнить I с 2
0043E34B ... jle TForm1.FormCreate + $22 ; Если меньше или равно, перейти на адрес $43E356 ($43E334 + $22)
0043E34D ... mov [ebp-$0c], $00000001 ; Это J := 1 - наша ветка then
0043E354 ... jmp TForm1.FormCreate + $29 ; Перейти на адрес 43E35D ($43E334 + $29)
0043E356 ... mov [ebp-$0c], $00000002 ( сейчас он нам неинтересен и поэтому вместо него я поставил многоточие)
Идем дальше. Предыдущий этап находится здеcь:
http://delphimaster.net/view/14-1046809017/

Продолжаем изучать основы устройства и работы коипьютера, продолжаем осваивать основы низкоуровневого программирования. Используя все тот же MK, но сопоставляя его с ПК. Сейчас наша задача - закончить рассмотрение команд перехода и подойти кследующей (и ОЧЕНЬ важной!) теме - адресации.

Простейшую команду перехода (безусловный переход) мы уже рассматривали, а когда Вы писали программы решения уравнений, то при проверке числа на ноль наверняка использовали либо команду F X=0, либо противоположную ей F X‡0. Вот это уже команды УСЛОВНОГО перехода - "перейти по указанному адресу, если содержимое RX равно (или не равно) нулю". Кроме них, в МК существуют еще команды F X>=0 и F X<0, а в ПК набор подобных команд намного шире. Перечень команд условного перехода для процессора 8088 такой: JA/JNBE, JAE/JNB/JNC, JB/JNAE/JC, JBE/JNA, JCXZ, JE/JZ, JG/JNLE, JGE/JNL, JL/JNGE, JLE/JNG, JNE/JNZ, JNO, JNP/JPO, JNS, JO, JP/JPE, JS. Мнемоника этих команд довольно простая, например: J-jump (перейти), N-not (не), G-greater (больше), E-equal (равно), L-lesser (меньше), C-carry(перенос), Z-zero (ноль), O-overflow (переполнение), P-parity (четность), S-sign (знак). Скажем, JNGE означает "перейти, если не больше и не равно", JZ - "перейти, если ноль", а JNO - "перейти, если нет переполнения". Но дело, конечно, не в количестве команд и не в их названиях (все это мы всегда можем найти в справочнике), а в том, как они работают. Вот это нам и нужно понять.

Когда-то мы уже говорили о регистре флагов и о том, что в нем существуют флаги переноса (CF) и переполнения (OF). Помимо них, в этом регистре еще есть флаги нуля (ZF - устанавливается при нулевом результате выполнения команды), четности (PF - устанавливается, если младший байт этого результата содержит четное число единиц) и знака (SF - всегда равен старшему биту результата). Вот с этими флагами и работают команды безусловного перехода. Например, пусть содержимое регистра EAX равно FFFFFFFF и выполняется такой кусок программы:

INC EAX ; увеличить EAX на 1
JZ LBL ; если ноль, перейти на адрес, помеченный в программе идентификатором LBL

После выполнения первой команды EAX будет равно нулю и выставится флаг ZF. Вторая команда проверит этот флаг, увидит, что он выставлен - и произойдет переход по адресу LBL. Все просто. Примерно так же сработает и такой кусок:

SUB EBX, EAX ; вычесть EAX из EBX и записать результат в EBX
JNE LBL ; если не равно, перейти по адресу LBL

Если EAX и EBX были равны, то после выполнения первой команды выставится флаг ZF, и перехода по адресу LBL не будет. А если EAX и EBX не были равны, то после выполнения первой команды флаг ZF, наоборот, сбросится и переход будет выполнен.

Рассмотрим маленькую иллюстрацию, которая, к тому же, послужит вступлением к нашей следующей теме - адресации. Сделайте в Delphi новый проект, дважды кликните по пустой форме и в появившемся обработчике события OnCreate напишите вот что:

procedure TForm1.FormCreate(Sender: TObject);
var
I, J: Integer;
begin // Здесь поставьте BreakPoint
I := 4;
If I > 2 then J := 1 else J := 2;
end;

Теперь в меню Delphi выберите Project | Options, в диалоге на закладке Compiler снимите птичку Optimization и нажмите ОК. Далее поставьте точку останова (BreakPoint) на строке begin (для этого щелкните по ней на левом поле редактора) и запустите программу. После остановки на BreakPoint в меню Delphi выберите View | Debug Windows | CPU - и Вы увидите окно CPU с ассемблерным кодом нашей программы, а в нем примерно вот такой кусок:

0043E334 ... push ebp ; Это точка входа в наш обработчик OnCreate. Ее адрес - $43E334.
...
0043E340 ... mov [ebp-$08], $00000004 ; Это I := 4
0043E347 ... cmp dword ptr [ebp-$08], $02 ; Сравнить I с 2
0043E34B ... jle TForm1.FormCreate + $22 ; Если меньше или равно, перейти на адрес $43E356 ($43E334 + $22)
0043E34D ... mov [ebp-$0c], $00000001 ; Это J := 1 - наша ветка then
0043E354 ... jmp TForm1.FormCreate + $29 ; Перейти на адрес 43E35D ($43E334 + $29)
0043E356 ... mov [ebp-$0c], $00000002 ; Это J := 2 - наша ветка else
0043E35D ...


Мы видим последовательность команд, по одной команде в каждой строке. В первом столбце находится адрес команды, во втором - ее машинный код (сейчас он нам неинтересен и поэтому вместо него я поставил многоточие), а далее идет ассемблерный код этой команды и после точки с запятой - мои комментарии. Все числа здесь, конечно же, шестнадцатиричные (и поэтому перед ними стоит знак $).

===== см. продолжение =====


 
Юрий Зотов   (2003-07-06 13:33) [1]

===== продолжение =====

Что это за филькина грамота? А это и есть код нашего метода FormCreate после его обработки компилятором.

EBP - это один из регистров CPU (регистр базы - Base Pointer). В нем хранится адрес, относительно которого рассчитываются другие адреса. Например, мы видим, что нашу переменную I компилятор разместил в памяти по адресу EBP-$8, а переменную J - по адресу EBP-$С. То есть, чтобы найти адрес I, нужно из числа, хранящегося в EBP вычесть $8. Вот это $8 называется СМЕЩЕНИЕМ и любое смещение всегда идет относительно какого-то базового адреса, а такой способ адресации называется "адресация со смещением". В строках 43E34B и 43E454 тоже используется адресация со смещением, но в качестве базового компилятор задал адрес точки входа в обработчик OnCreate (он равен $43E334), а в качестве смещения - рассчитал и указал константы $22 и $29.

Итак, в строке 43E347 команда CMP сравнивает переменную I с двойкой, просто вычисляя I - 2 и выставляя при этом флаги ZF, SF и OF. В нашем случае результат будет больше нуля и переполнения нет, поэтому все эти флаги будут равны нулю (сброшены). Далее команда JLE проверяет условие (ZF=1) or (SF<>OF). Оно не выполняется, поэтому перехода на строку 43E356 не происходит и наша переменная J получает значение 1, после чего команда JMP выполняет безусловный переход на строку 43E35D - и программа пошла работать дальше. Если бы I было равно 2, то мы получили бы ZF=1, SF=0 и OF=0, произошел бы переход на строку 43E356 и переменная J получила бы значение 2. А если бы I было меньше 2, то мы получили бы ZF=0, SF=1, OF=0 и произошло бы то же самое. И в любом случае программа продолжает работу со строки 43E35D.

Обратите внимание, что написанное нами условие if I > 2 компилятор как бы "подменил" обратным условием JLE. Почему? Да просто потому, что он так написан. А написан он так потому, что в ряде случаев такие "подмены" упрощают сам компилятор или позволяют ему построить более эффективный код. Ведь совершенно неважно, точно ли машинный код соответствует исходному, или не точно. Важно, чтобы он точно соответствовал ему ПО СМЫСЛУ, давал правильный результат и был наиболее эффективным.

И еще обратите внимание на то, что никаких переменных I и J в машинном коде уже нет. Точнее, они, конечно, есть, но в виде АДРЕСОВ, а не в виде каких-то имен. Поэтому иногда задаваемые вопросы типа "как получить имя переменной, зная ее адрес" (да еще в чужой программе) по меньшей мере просто наивны. И по той же причине (а также и по куче других причин) ТОЧНЫЙ обратный перевод машинного кода на язык высокого уровня (декомпиляция) невозможен. Возможна СМЫСЛОВАЯ, но не точная декомпиляция.

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

if ПРАВИЛЬНЫЙ_РЕЗУЛЬТАТ_СИСТЕМЫ_ЗАЩИТЫ then РАБОТАТЬ else НЕ_РАБОТАТЬ;

Как Вы теперь уже понимаете, Ваш оператор if компилятор превратит в какую-то команду условного перехода, например, в JNE (переход, если не равно). Что делает хакер? Он отыскивает в коде Вашей программы это место и код команды JNE заменяет кодом обратной ей команды JE (переход, если равно). Вот и все, программа взломана. Ветки then и else поменялись местами и вся Ваша суперпуперзащита оказалась попросту ненужной - потому что ее никто даже и не пытался ломать, ее просто обошли. Так что помимо самой системы защиты нужно еще сделать так, чтобы хакеру было очень трудно отыскать то место, где проверяется результат ее работы.

===== см. окончание =====


 
Юрий Зотов   (2003-07-06 13:34) [2]

===== окончание =====

Ну вот, пожалуй и все о командах перехода. Они довольно просты, но теперь, зная о них, мы с Вами должны понимать "внутреннюю" сущность таких операторов, как if, case, goto, for, while, repeat и им подобных. Компилятор превращает их в набор команд, которые сначала вычисляют условие перехода, а затем выполняют (или НЕ выполняют) сам переход. Только и всего. Причем заметьте - совершенно неважно, на каком именно языке эти операторы изначально были написаны и как они на этом языке называются - case, select или как-то еще. Какая разница? После компиляции они все равно превратятся практически в один и тот же набор команд (ну, возможно, с мелкими отличиями). Поэтому, например, споры о том, какой язык лучше, Паскаль или Си чаще всего бывают просто бессмысленны. Если уж сравнивать, то не языки, а компиляторы - какой работает быстрее, какой строит более эффективный код и т.д. Причем даже не обязательно компиляторы с разных языков, потому что два компилятора с одного и того же языка по своим конечным результатам запросто могут отличаться друг от друга гораздо сильнее, чем два компилятора с разных языков.

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

Кстати, о циклах for. Они всегда имеют переменную - счетчик цикла. Но где эта переменная размещается? Ясно, что наиболее выгодно разместить ее не в памяти, а прямо в одном из регистров CPU - тогда все операции с ней будут происходить быстрее. Кроме того, выгоднее строить цикл, не увеличивая, а уменьшая значение счетчика. Тогда по завершении цикла он окажется равным нулю, будет выставлен флаг CF и для проверки условия выхода не потребуется специальных команд - достаточно будет команды JZ (или JNZ). Именно так и поступает компилятор Delphi, если в опциях проекта включена оптимизация. Но ведь после завершения такого цикла тот же самый регистр, в котором хранился счетчик будет использован уже для чего-то другого, а сам счетчик как бы "исчезнет". Вот почему в таких случаях говорят, что значение счетчика цикла после выхода из цикла будет неопределенным (то есть, любым). И вот почему компилятор в таких случаях просит, чтобы счетчик цикла был объявлен, как простая локальная переменная - потому что непростую он не может разместить в регистре, а нелокальную не имеет права в нем размещать, иначе ее изменения будут потеряны, что может нарушить логику программы.

И домашнее задание.

1. В прошлый раз мы писали МК-программы для решения линейного уравнения AX+B=0 и квадратного уравнения AX^2+BX+C=0. Если в квадратном уравнении задать A=0, то оно превращается в линейное, но решение все равно имеет. Напишите программу решения квадратного уравнения, учитывающую эту возможность.

2. Написать в рассмотренном выше методе FormCreate цикл for, а затем сравнить его ассемблерный код при включенной и отключенной оптимизации, а также в случаях, когда счетчик цикла объявлен, как локальная и как глобальная переменная. Обязательно обратите внимание на сообщения компилятора, переведите их на русский язык, разберитесь почему они возникают и какой имеют смысл.

3. Напишите в рассмотренном выше методе FormCreate следующее:

procedure TForm1.FormCreate(Sender: TObject);
begin
if Sender = Self then Halt
end;

Мы получили программу, которая запускается и тут же завершается. То есть, как бы "защищенную" программу, которая как бы проверила свою легальность и работать отказывается. Задание - "взломать" эту программу. То есть, заставить ее работать, исправляя не ее исходный текст, а ее машинный код. Для исследования машинного кода используйте отладчик Delphi и окно CPU, а для его правки - любой HEX-редактор. Подсказка - для "взлома" достаточно найти команду jnz TForm1.FormCreate+19 (ее машинный код $7505) и заменить ее обратной командой jz (ее машинный код будет $7405). Задание это не такое простое, может и не получиться. Ничего страшного, польза будет уже от того, что Вы покопаетесь в машинном коде.


 
SPeller   (2003-07-06 16:35) [3]

Оффтопик, но всё же. Может, у кого-то остались первые три ветки с уроками - интересно мне вдруг стало, хочу поделать. Чтобы не засорять форум, прошу отослать их мне на мыло. Буду очень признателен.


 
Palladin   (2003-07-06 16:42) [4]

http://www.baseprogram.narod.ru


 
Anatoly Podgoretsky   (2003-07-06 16:43) [5]

Вроде бы кто то делал сайт.


 
SPeller   (2003-07-06 16:50) [6]

Спасибо. Бум учиться уму-разуму :)


 
Юрий Зотов   (2003-07-06 17:13) [7]

Блин, нашел досадную "очепятку"...

В последнем абзаце, перед домашним заданием:
"Тогда по завершении цикла он окажется равным нулю, будет выставлен флаг CF..."

Конечно, флаг ZF, а не CF. Остальное верно.


 
k-man   (2003-07-06 20:56) [8]

Спасибо пребольшое Юрию Зотову.
Я увидев эту ветку пристально изучил ее содержимое немного покраснев от названия - все-таки год стажа. Тем не менее узнал много нового.


 
Юрий Зотов   (2003-07-07 06:15) [9]

Up.


 
Skier   (2003-07-07 08:13) [10]

Юрию Зотову большое решпектование !


 
Polevi   (2003-07-07 10:16) [11]

с удовольствием прочел


 
AlexRush   (2003-07-07 12:23) [12]

Небольшое исследование оптимизации dcc32 14.0:
Код на паскале:

program Project2;

function TestProc1(param32bit1,param32bit2:CARDINAL):CARDINAL;export;
var val32bit1,
val32bit2:CARDINAL;
begin
val32bit1:=param32bit2;
val32bit1:=val32bit1+1;
val32bit2:=param32bit2+param32bit1;
end;

EXPORTS TestProc1;

begin
( 1,2)
Небольшое исследование оптимизации dcc32 14.0:
Код на паскале:

program Project2;

function TestProc1(param32bit1,param32bit2:CARDINAL):CARDINAL;export;
var val32bit1,
val32bit2:CARDINAL;
begin
val32bit1:=param32bit2;
val32bit1:=val32bit1+1;
val32bit2:=param32bit2+param32bit1;
end;

EXPORTS TestProc1;

begin
TestProc1(1,2);
end.


Код, сгенерированный БЕЗ оптимизации:

00401E18 public TestProc1
00401E18 TestProc1 proc near ; CODE XREF: CODE:00401EA2p
00401E18
00401E18 var_14 = dword ptr -14h
00401E18 var_10 = dword ptr -10h
00401E18 var_C = dword ptr -0Ch
00401E18 var_8 = dword ptr -8
00401E18 var_4 = dword ptr -4
00401E18
00401E18 push ebp
00401E19 mov ebp, esp
00401E1B add esp, 0FFFFFFECh
00401E1E mov [ebp+var_8], edx
00401E21 mov [ebp+var_4], eax
00401E24 mov eax, [ebp+var_8]
00401E27 mov [ebp+var_10], eax
00401E2A inc [ebp+var_10]
00401E2D mov eax, [ebp+var_8]
00401E30 add eax, [ebp+var_4]
00401E33 mov [ebp+var_14], eax
00401E36 mov eax, [ebp+var_C]
00401E39 mov esp, ebp
00401E3B pop ebp
00401E3C retn
00401E3C TestProc1 endp


Код, сгенерированный C оптимизацией:


00401E18 public TestProc1
00401E18 TestProc1 proc near ; CODE XREF: CODE:00401E7Ep
00401E18 retn
00401E18 TestProc1 endp


Отак - то ! :)))))))))


 
AlexRush   (2003-07-07 13:19) [13]

Идеологический вопрос по оптимизациив dcc32 к Юрию Зотову и всем остальным:
Паскаль в конструкции CASE не позволяет использовать переменые языка:

var VarVal:integer;
....
case SomeOne of
001 : do1;
002 : do2;
VarVal ( param32bit1,param32bit2:CARDINAL)
Идеологический вопрос по оптимизациив dcc32 к Юрию Зотову и всем остальным:
Паскаль в конструкции CASE не позволяет использовать переменые языка:

var VarVal:integer;
....
case SomeOne of
001 : do1;
002 : do2;
VarVal : do3;// CONSTANT EXPRESSION EXCEPTED
end;

При реализации оператора выбора на ассемблере часто применяют карту переходов. Это может съесть много памяти, но в отдельных случаях прирост в скорости коллосальный. Например, В MFC и VCL карты переходов строятся в главной оконой процедуре для обработки сообщений системы.
В dcc32 case реализован классическим способом:

function TestProc1(param32bit1,param32bit2:CARDINAL):CARDINAL;export;
var val32bit1:cardinal;
begin
case param32bit1 of
$0F0F0F0F: val32bit1:=1;
$0A0A0A0A: val32bit1:=7;
$0E0E0E0E: val32bit1:=3;
end;
result:=val32bit1+param32bit2;
end;


С оптимизацией:


00401E18 public TestProc1
00401E18 TestProc1 proc near ; CODE XREF: CODE:00401EA7p
00401E18 sub eax, 0A0A0A0Ah
00401E1D jz short loc_401E34
00401E1F sub eax, 4040404h
00401E24 jz short loc_401E3B
00401E26 sub eax, 1010101h
00401E2B jnz short loc_401E40
00401E2D mov ecx, 1
00401E32 jmp short loc_401E40
00401E34 ; -----------------------------------------------------------------
00401E34
00401E34 loc_401E34: ; CODE XREF: TestProc1+5j
00401E34 mov ecx, 7
00401E39 jmp short loc_401E40
00401E3B ; -----------------------------------------------------------------
00401E3B
00401E3B loc_401E3B: ; CODE XREF: TestProc1+Cj
00401E3B mov ecx, 3
00401E40
00401E40 loc_401E40: ; CODE XREF: TestProc1+13j
00401E40 ; TestProc1+1Aj ...
00401E40 lea eax, [edx+ecx]
00401E43 retn
00401E43 TestProc1 endp


Так вот собственно, вопрос: Есть ли настройка/опция компилятора, с которой case"ы будут переводится в карты переходов ?

Кстати, С Оптимизацией код result:=val32bit1+param32bit2; преобразуется в lea eax, [edx+ecx], в то время как без оной:

00401E55 mov eax, [ebp+var_10]
00401E58 add eax, [ebp+var_8]
00401E5B mov [ebp+var_C], eax
00401E5E mov eax, [ebp+var_C]

Использование lea меня порадовало :)


 
AlexRush   (2003-07-07 13:24) [14]

Продолжение вопроса:
Если все-таки карты переходов не применяются, а идет поэлементное сравнение, то почему бы не добавить возможность использовать в case переменные ? IMHO было бы удобно. Или это противоречит како-либо парадигме програмирования ??


 
VD601   (2003-07-07 22:36) [15]

Ура! Юрий, Вы молодец! Ветку Ап! ЮЗ тоже! Качай его, ребята!!!


 
Kair   (2003-07-09 20:58) [16]

Че та хотел спросить, но забыл. :)


 
Makhanev A.S.   (2003-07-10 00:10) [17]

Отличная ветка, одна из лучших!
Up!


 
Marser   (2003-07-10 00:23) [18]

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


 
pasha_golub   (2003-07-10 17:51) [19]

Cool ;-)


 
Skier   (2003-07-11 10:54) [20]

Up.



 
Юрий Зотов   (2003-07-12 11:03) [21]

Up. Пока в архив не свалилось.

И приглашение к обсуждению - см. здесь:
http://delphimaster.net/view/14-1046809017/


 
Юрий Зотов   (2003-07-21 15:33) [22]

Снова Up.


 
iNew   (2003-07-21 17:33) [23]

Просьба у кого остались предыдущие 4 ветки скиньте на мыло.
P.S. http://www.baseprogram.narod.ru не работает.



 
Юрий Зотов   (2003-07-27 10:43) [24]

Что-то нет никаких вопросов...

Народ, а в этом проекте вообще кто-нибудь, кроме меня, остался?
Или стрельба в воздух идет? Пожалуйста, отзовитесь, но только те, кто ДЕЙСТВИТЕЛЬНО эти материалы читает, честно в них разбирается, честно выполняет все задания и т.д.


 
Marser   (2003-07-27 11:33) [25]


> Marser © (10.07.03 00:23)
> Удалено модератором
> Примечание: До тех пор пока не будут принесены публичные
> извинения за атаку на форум, игнорирование распоряжений
> модераторов, нападки на модераторов, призывы к другим участика
> по организации флудаа, тебе и Malder писать в форумы не
> надо, Аристарх свои извинения принес.

Очень прошу модераторов вырвать это и подобные сообщения с корнем, а то нехорошие воспоминания в голову сразу лезут...


 
Marser   (2003-07-27 12:13) [26]


> Юрий Зотов ©

Почитываем потихоньку...Многое ещё в школе было, кое-что сам и в универе ещё много будет...


 
Vlad Oshin   (2003-07-27 16:34) [27]


> Юрий Зотов © (27.07.03 10:43)

Читаю всегда, но вот беда - все понятно.
То есть дело вот как обстоит. Как в университете перед экзаменом.
Читаю - понятно, листаю, листаю - понятно, еще листаю - непонятно. Возвращаюсь - понятно. Читаю подряд - понятно, понятно.. оба на! ничего не понял...

Вот Ваши уроки понятны. Но смотрю какие-нибудь исходники из сети - непонятно...
....Сильно жду про адресацию :)...



 
VD602   (2003-07-27 22:04) [28]

> Народ, а в этом проекте вообще кто-нибудь, кроме меня, остался?

Да, можете быть уверены. Более того - с течением времени т.н. "курс ЮЗ" будет приобретать все большую популярность.


 
Sl1der   (2003-07-27 23:36) [29]

Я читаю. Жду следующего этапа. Может какие-нибудь задачки на этот урок, пока новый не готов.(желательно поинтереснее)


 
Юрий Зотов   (2003-07-27 23:44) [30]

> Sl1der (27.07.03 23:36)

А программу уже взломали (задание №3)?

Если нет - ломайте. Если да, то хотелось бы знать, было ли это сложно и что именно было самым сложным?


 
race1   (2003-07-28 08:49) [31]

>Юрий Зотов © (27.07.03 23:44)
Если нет - ломайте. Если да, то хотелось бы знать, было ли это сложно и что именно было самым сложным?

самым сложным было понять как ломаются другие программки без исходных кодов в Hex едиторах :)) когда после 20-ой замены 7505 на 7405 программа запустилась ;)


 
Юрий Зотов   (2003-07-28 09:04) [32]

> race1 © (28.07.03 08:49)

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


 
Bel   (2003-07-28 10:01) [33]

> Народ, а в этом проекте вообще кто-нибудь, кроме меня, остался?

Внесу и свои 5 копеек. Не сомневайтесь, остались, и многие.
Для меня это в основном вспоминание того, что проходил в институте, но есть и кое-что новое.


 
AlexRush   (2003-07-28 10:50) [34]

> Юрий Зотов © (27.07.03 10:43)
> Что-то нет никаких вопросов...
- ну как это нет, я вот свои задал две недели назад....

2Юрий Зотов ©: Так все-таки, что по повду AlexRush © (07.07.03 13:24) ?


 
Юрий Зотов   (2003-07-28 11:45) [35]

> AlexRush © (28.07.03 10:50)

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


 
chs2r   (2003-07-28 15:04) [36]

а где предыдущие уроки найти?
по первой ссылке пишут удалено или перемещено


 
AlexRush   (2003-07-28 15:09) [37]

Юрий Зотов © (28.07.03 11:45)
> Тема интересная, но все же для другой ветки.
- так значит поднимем тему ? Она для меня действительно интересна. И, думаю, не только мне.


 
Юрий Зотов   (2003-07-28 15:19) [38]

> chs2r © (28.07.03 15:04)

Внизу страницы есть ссылка на архивы. Увы, пока придется искать в них. Нужны такие ссылки:
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1035122594&n=3
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1035226023&n=3
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1035836141&n=3
http://delphi.mastak.ru/cgi-bin/forum.pl?look=1&id=1038768556&n=3

Вопрос с централизацией "уроков" решается, но, увы, еще не решен. Так что пока см. архивы и ориентируйтесь по номерам ID.


> AlexRush © (28.07.03 15:09)

Давайте поднимем, действительно интересно. Может, и я че умное вякну, а уж других-то наверняка послушаю с удовольствием.


 
AlexRush   (2003-07-28 16:59) [39]

2Юрий Зотов © (28.07.03 15:19) - Ок, пришлашаю на http://delphimaster.net/view/14-1046809017/


 
Malder   (2003-07-28 17:53) [40]

Не по моей вине и к моему удивлению произошли странности с сайтом http://www.baseprogram.narod.ru

Сейчас работа восстановлена.

to Юрий Зотов
пока я поддерживаю сайт, но ищется человек, который этим будет вместо меня заниматься



Страницы: 1 2 3 4 вся ветка

Форум: "Потрепаться";
Текущий архив: 2003.10.06;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.66 MB
Время: 0.011 c
4-18686
Delphi5.01
2003-08-01 20:26
2003.10.06
GetParent, a kak poluchit GetChild


1-18446
Adil Aliev
2003-09-24 17:36
2003.10.06
IE Toolbars


9-18214
K.o.Z
2003-03-02 00:24
2003.10.06
Помогите вычеслить


3-18218
Andriy Tysh
2003-09-17 15:55
2003.10.06
Resize of Collumn in DBGrid


3-18262
McSimm2
2003-09-17 15:31
2003.10.06
Кодирование данных





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский