Форум: "Прочее";
Текущий архив: 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