Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2017.04.09;
Скачать: CL | DM;

Вниз

Вопрос про ASM команду sub   Найти похожие ветки 

 
KSergey ©   (2016-02-04 13:54) [0]

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

Это были извинения за то, что такой вопрос задаю. Вопрос:

Есть дизассемблированный код, в нём:
len - integer
pNonSpace, pStart - указатели pChar

> pas:  len := pNonSpace - pStart + 1;
mov  ecx, edi
sub  exc,[ebp-$0c]
jno здесь адрес перехода на "add  ecx, 01"
call @IntOver
add  ecx, 01
.......


Ну и далее там что-то, не важно.


 
KSergey ©   (2016-02-04 13:58) [1]

Собственно вопрос:
Какие должны быть операнды  в
   sub  exc,[ebp-$0c]
чтобы после неё взвёлся флаг OF ?

Я думал, что оба операнда, например, должны быть больше MaxInt, но почему-то нет.
Или exc (оно же pNonSpace) должно быть больше MaxInt, а вычитаемое (т.е. pStart) должно быть меньше MaxInt?

(ну я предполагаю, что указатели - эти беззнаковый величины же и поэтому могут быть больше, чем знаковый Int)


 
KSergey ©   (2016-02-04 14:43) [2]

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

По моему вопросу: нужен вариант номер 2, т.е. чтобы pNonSpace было более MaxInt, а pStart - менее MaxInt


 
Rouse_ ©   (2016-02-04 14:45) [3]

ну к примеру в ECX $80000000 а в памяти по адресу [EBP - $C] значение $7FFFFFFF


 
KSergey ©   (2016-02-04 15:22) [4]

Я, признаться, никак не могу сообразить логику выставления этого флага.
Ну разве что он применим (осмысленен) сугубо для signed int типов, а для unsigned int смысла не имеет?


 
KSergey ©   (2016-02-04 15:24) [5]

( друзья, я в общем-то в теме и осознаю, что для процессора нет разницы между signed и unsigned типами, и что это лишь вопрос трактовки; но именно трактовку и "бизнес смысл" и пытаюсь понять)


 
Inovet ©   (2016-02-04 15:50) [6]

123-124 не выставляется?


 
Rouse_ ©   (2016-02-04 15:52) [7]


> Ну разве что он применим (осмысленен) сугубо для signed
> int типов, а для unsigned int смысла не имеет?

Процессор не знает о том что за число (SIGNED/UNSIGNED) поэтому это возлагается на компилятор, который генерирует различные инструкции условного перехода при работе с такими типами.

К примеру

var
 A, B: DWORD;
...
   if A < B then


Здесь будет использоваться инструкция JBE в которой задействованы флаги CF и ZF, а вот для такого случая:

var
 A, B: Integer;
...
   if A < B then


Будет использоваться инструкция JLE где прыжок осуществляется уже по совокупности флагов ZF, SZ и OF

А флаги будут выставляться всегда.


 
Rouse_ ©   (2016-02-04 15:55) [8]


> Inovet ©   (04.02.16 15:50) [6]
> 123-124 не выставляется?

нет конечно


 
Rouse_ ©   (2016-02-04 15:57) [9]

Если есть желание разобраться по какому принципу выставляются флаги - то вот пример (сори на сях - но там все очень просто): http://rouse.drkb.ru/tmp/cmp.zip


 
Rouse_ ©   (2016-02-04 16:01) [10]

ЗЫ: в vmCMP8() происходит вычитание второго числа из первого - как раз искомый SUB


 
Inovet ©   (2016-02-04 16:07) [11]

> [8] Rouse_ ©   (04.02.16 15:55)

Полез проверять.

mov eax, 124
sub eax, 1   ; Сбросился
mov eax, 124
sub eax, ecx ; Выставился. Уф.


 
Rouse_ ©   (2016-02-04 16:13) [12]


> Inovet ©   (04.02.16 16:07) [11]

Ты точно про OF флаг говоришь?
Этот код не выставляет OF флаг.


 
Inovet ©   (2016-02-04 16:18) [13]

> [12] Rouse_ ©   (04.02.16 16:13)
> Ты точно про OF флаг говоришь?

Блин, а я ж про CF думал.:)


 
KSergey ©   (2016-02-04 16:20) [14]

А всё же, логика выставления OF флага?


 
Rouse_ ©   (2016-02-04 16:21) [15]


> Inovet ©   (04.02.16 16:18) [13]
> > [12] Rouse_ ©   (04.02.16 16:13)
> > Ты точно про OF флаг говоришь?
>
> Блин, а я ж про CF думал.:)

Угу я даж ролик успел снять, подумал мошт у меня крыша поехала :)
http://rouse.drkb.ru/tmp/1.mp4


 
Rouse_ ©   (2016-02-04 16:26) [16]


> KSergey ©   (04.02.16 16:20) [14]
> А всё же, логика выставления OF флага?

так она простая:

if (!aBit && bBit && flags.SF)
 flags.OF = true;
if (aBit && !bBit && !flags.SF)
 flags.OF = true;


т.е. смотрим старшие биты у обоих чисел (это SIGN бит и смотрим SF флаг, который выставляется от операции сложения первого и инвертированного второго числа).

Грубо говоря этим мы проверяем - происходил ли переход через $80000000 (перенос бита в более старший разряд)


 
Inovet ©   (2016-02-04 16:36) [17]

> [16] Rouse_ ©   (04.02.16 16:26)
> так она простая

Для интереса в Вики посмотрел - есть там!
https://ru.wikipedia.org/wiki/%D0%A4%D0%BB%D0%B0%D0%B3_%D0%BF%D0%B5%D1%80%D0%B5%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F


 
Rouse_ ©   (2016-02-04 16:36) [18]

Давай попробую по другому, вот смотри пример от Inovet
От числа 123 отнимает 124.
Отнимать будем через сложение, т.е. выразим как оба этих числа (в 16 ричной) как
7B (123)
и FFFFFF84 (минус 124)

сложим их - получим результат = $FFFFFFFF т.е. число минус 1 - которое полностью укладывается в диапазон 32 бит.

Теперь берем пой пример:
первое число $80000000
второе $7FFFFFFF

второе инвертируем: оно становится равно $80000001

складываем - на выходе число: $100000001 - а вот оно уже в 32 бита не влезет, самый старшая единичка находится в 33-ем бите - оть это и есть переполнение.

Так понятно?


 
Pavia ©   (2016-02-04 16:43) [19]


> А всё же, логика выставления OF флага?

Флаг OF взводится если результат не влазит в размеры операнда. Операнд для этого флага трактуется как знаковый.
SInt8 = от -128 до 127
К примеру
SUB (-128), 1
Результат -129 не влазит в SInt8 следовательно возводится OF.
SUB 1, -127
Результат 128 не влазит в SInt8 следовательно возводится OF.


function SUB8(a,b:UInt8):UInt16;
begin
Result:=a-b;
_ZF:=Ord(Result=0);
_SF:=(Result  shr 7)  and 1;
_PF:=PF_Table[Result and $FF];
_OF:= (((a xor b) and (a xor result)) shr 7)and 1;
_CF:=(Result  shr 8) and 1;

_AF:=((a xor b xor result) shr 4) and 1;
end;


 
Rouse_ ©   (2016-02-04 16:50) [20]


> Pavia ©   (04.02.16 16:43) [19]

Что за PF_Table, покажи плз


 
Rouse_ ©   (2016-02-04 17:00) [21]

А все - не надо, собственно сам по быстрому построил :)


 
Pavia ©   (2016-02-04 17:00) [22]

Я уже не помню что там к чему.

for i:=0 to 255 do
PF_Table[i]:=1 and (1 xor i xor (i shr 1) xor (i shr 2) xor (i shr 3)
               xor (i shr 4) xor (i shr 5) xor (i shr 6) xor (i shr 7));


 
Rouse_ ©   (2016-02-04 17:04) [23]

Parity флаг - четное кол-во включенных бит в младшем байте (True/False).


 
KSergey ©   (2016-02-04 18:04) [24]

> Rouse_ ©   (04.02.16 16:36) [18]

Да, мне всё понятно. Спасибо.

> Pavia ©   (04.02.16 16:43) [19]

И вам тоже спасибо!


 
Rouse_ ©   (2016-02-04 18:06) [25]

Обращайся :)


 
Rouse_ ©   (2016-02-04 18:14) [26]

Да и кстати, по поводу мануалов: http://www.intel.ru/content/www/ru/ru/processors/architectures-software-developer-manuals.html

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


 
KSergey ©   (2016-04-07 15:42) [27]

Как-то я не отписался о сути. Проблема разобрана, хоть от этого и не легче.

Оказалась совершенно неожиданная мерзопакость в D5 в том, что вот в таком коде

   len: Integer;
   pStart, pNonSpace: PChar;
.....
   len := pNonSpace - pStart + 1;

при включенной опции компилятора "Check inneger overflow" компилятор после выражения pNonSpace - pStart впендюривает проверку на переполнение Int"а.
Причем не зависимо от типа переменной len: хоть Integer, хоть Cardinal. И даже если +1 убрать.

И как только получается так, что pNonSpace указывает на адрес за границей 2 Гб, а  pStart указывает на адрес до 2 Гб (при этом разница может быть и совсем небольшой) - получаем EIntegerOverflow на этой строке.

Кто догадался такую проверку вставить для указателей - не знаю.


 
Rouse_ ©   (2016-04-07 16:21) [28]

А так?
len := Integer(pNonSpace - pStart + 1);


 
Rouse_ ©   (2016-04-07 16:29) [29]

Не, соврал:

var
  len: DWORD;
  pStart, pNonSpace: PAnsiChar;
begin
 try
   pStart := Pointer($7FFFFFFF);
   pNonSpace := pStart + $FFFFFF;
  len := DWORD(pNonSpace) - DWORD(pStart) + 1;


 
Rouse_ ©   (2016-04-07 16:36) [30]

Вот а логика простая, это можно увидеть из асм кода - изначально PChar кастится к Integer (так всегда было), стало быть использует при проверке OF флаг в частности генерацией JNO инструкции.
Нужно всего лишь объяснить компилеру что у нас тут переполнения по SIGN-биту нет, сделав каст любому устраивающему нас UNSIGNED типу (DWORD/Cardinal/ULong и т.п.)

В этом случае компилер сгенерирует JNB инструкцию, и все решиться нормально.


 
KSergey ©   (2016-04-07 19:29) [31]

> Rouse_ ©   (07.04.16 16:36) [30]
> сделав каст любому устраивающему нас UNSIGNED типу (DWORD/Cardinal/ULong и т.п.)

Это да.
Но скажите мне: кто в борланде решил, что поинтер в Win32 - знаковый?!
Я понимаю, что в ту пору (примерно Windows 95, я думаю) про достижение 2Гб памяти и подумать никто не мог (к вопросу о странном развитии техники), но всё же теория-то была изложена, а теория - она про 4Гб (и 32-х битные указатели) сразу была!

Ну и потом: в своём коде я, конечно, могу переписать, но есть и "не мой" код, весь не перепроверишь.

Интересно, в текущих версиях дельфи - так же?


 
Rouse_ ©   (2016-04-07 19:37) [32]

Ну смотри в 32 битых ты оперируешь памятью до 7fffffff - вылезешь за нее будет больно.
Логично? Да еще как


 
KSergey ©   (2016-04-07 19:47) [33]

> Rouse_ ©   (07.04.16 19:37) [32]
> Ну смотри в 32 битых ты оперируешь памятью до 7fffffff

Это почему?! почему на ваш взгляд  8-й проводок в старшем байте не может принять состояние логической единицы? чем он такой особенный?
я не понимаю.


 
Inovet ©   (2016-04-07 20:46) [34]

> [33] KSergey ©   (07.04.16 19:47)
> Это почему?! почему на ваш взгляд  8-й проводок в старшем
> байте не может принять состояние логической единицы?

В Майкрософт тоже когда-то сложился знаковый тип? Ну как бы - вот вам половина, а остальное не трожьте.:)


 
Pavia ©   (2016-04-07 21:09) [35]

Для win 95-98 это ещё имело смысл. А вот в других ОС нет никакого смысла.


 
Игорь Шевченко ©   (2016-04-07 21:24) [36]


> Ну смотри в 32 битых ты оперируешь памятью до 7fffffff -
>  вылезешь за нее будет больно.


Не всегда


 
Rouse_ ©   (2016-04-08 00:38) [37]

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


 
Германн ©   (2016-04-08 01:30) [38]


> Rouse_ ©   (07.04.16 16:36) [30]
>
> Вот а логика простая, это можно увидеть из асм кода - изначально
> PChar кастится к Integer (так всегда было)

Ну вот а нафига так всегда было? :)


 
Rouse_ ©   (2016-04-08 02:02) [39]

Сереж, я ж уже объяснил, блин (че как дети прям, книжки не читаете) - 4 гига виртульной памяти дели на лапопам, первая твоя, вторая ядра.


 
Pavia ©   (2016-04-08 06:31) [40]


> Сереж, я ж уже объяснил, блин (че как дети прям, книжки
> не читаете) - 4 гига виртульной памяти дели на лапопам,
> первая твоя, вторая ядра.

Так у вас логика не правильная. Ядро отображалось в адресный процесс приложения для того что-бы приложение могло адресовать к ядру. Иначе нет смысла. К примеру чтение значение таймера. Поэтому ваша логика не верна.



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

Текущий архив: 2017.04.09;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.007 c
15-1460484629
Dmk
2016-04-12 21:10
2017.04.09
Регистрация Delphi


2-1439274792
olle
2015-08-11 09:33
2017.04.09
создать oleauto


15-1454583291
KSergey
2016-02-04 13:54
2017.04.09
Вопрос про ASM команду sub


15-1460401970
Юрий Зотов
2016-04-11 22:12
2017.04.09
Рисование контура окна


4-1282656910
Unknown_user
2010-08-24 17:35
2017.04.09
Запрет получения фокуса приложения