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

Вниз

Вопрос про 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.003 c
15-1460136529
aka
2016-04-08 20:28
2017.04.09
Лицензионное ПО


2-1439406925
oleg_teacher
2015-08-12 22:15
2017.04.09
Вопрос взаимодействия Delphi и Excel


2-1439285376
Masterucs
2015-08-11 12:29
2017.04.09
Delphi XE: изменили FreeAndNil?


2-1439375893
GAZot
2015-08-12 13:38
2017.04.09
Пакетная передача данных по протоколу UDP


2-1438151711
ВладОшин
2015-07-29 09:35
2017.04.09
По handle окна, можно определить готово ли оно к вводу? (Key/Mou)





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский