Scc прописывание значения byte -$FF
Вроде может если от -$7FFF до -$FFFF .
Нет таких чисел
Точнее, это не то, что ты имеешь в виду, а отрицательные числа -255 и др., записанные в прямом коде. Смотря на значения регистров, надо всегда думать об обратном коде.
http://ru.wikipedia.org/wiki/Прямой_код_(представление_числа)
http://ru.wikipedia.org/wiki/Обратный_код
http://ru.wikipedia.org/wiki/Дополнительный_код_(представление_числа)
А кому хочется мазохизма, читайте книжку
Садо Самофалова "Прикладная теория цифровых автоматов."
Там разобраны все нюансы.
Сами по себе значения в регистрах ничего о себе не говорят. Какое число они реально представляют, зависит от инструкции, она выбирает размер и вид записи числа (прямой/обратный) - то, что мы называем знаковой/беззнаковой операцией. Операции сложения и вычитания у 68k всегда беззнаковые, но это не значит, что они не работают с отрицательными числами, просто результат (в регистре, а не для человека) в обоих представлениях одинаковый. А уж как его интерпретировать - дело другое. И обработка переполнения и переноса (флаги C, V) на совести программиста. Основных проблем две: либо число не влезает в разрядность, либо в результате получается число другого знака - опять же из-за нехватки разрядов.
Примеры, включая проблемные. Пишу сходу, поэтому могу ошибаться.
1. $0064 + $FFFE = $0062
1) $FFFE значит -2, и всё нормально.
2) $FFFE - некое большое число 65534, из-за чего в результате сложения мы должны получить 65634 ($10062), которое не влезает в тип word.
Вот тут скорей всего $FFFE означает на самом деле -2, а такие исходные данные мы можем получить, например, когда к некой координате #$0064 прибавляется отрицательный шаг -2. Скажем, герой сделал шажок влево.
То, что содержимое регистра не говорит о его знаке, справедливо и для языков высокого уровня. Пример на паскале:
var
a, b : word;
c, d, e : smallint;
begin
a := 100;
b := $FFFE;
c := b; { Фактически, ячейка c содержит то же самое, что b, это можно посмотреть в памяти }
d := a + b;
e := a + c;
writeln( b );
writeln( c );
writeln( d );
writeln( e );
end.
2. $8001 + $8001 = $0002.
-32766 + (-32766) = 2
Получается число неправильного знака.
Но как правило, исходя из примера 1, лучше считать все числа знаковыми, особенно если они word.
Число $FF почти всегда означает именно -1, часто используется в качестве флага для операций TST. Оно так популярно, потому что его также легко установить: MOVEQ, Scc.
В теме "Геймдев для 68k" я объяснял назначение команд Scc, не помню, писал ли я там, почему в качестве флага применяется именно -1, а не +1.
Напомню про сами Scc: с их помощью можно вычислять
сложные логические выражения без использования прыжков. Например, конструкцию на паскале
isEqua := a = b;
можно записать так:
TST.w a, b
SEQ isEqua
А как быть, если выражение сложнее, чем одна операция сравнения? Тут и приходит на помощь число -1 = $FF и битовые операции. Как вы знаете, в C/C++ можно мешать логические и битовые операции, они даже обозначаются схоже. Вообще, изначально, на уровне одного бита логические и битовые операции работают идентично. Всё бы ничего, но в числах больше одного бита. В сях этот вопрос решили так: число 0 считается равным ЛОЖЬ, любое другое - ИСТИНА. И наоборот, ЛОЖЬ считается равной 0. Хорошо, а какое число си считает равным ИСТИНЕ по умолчанию, т.е. когда логическое значение приводится к числовому? В книжках по сях пишут, что +1, но я не проверял. А в M68k используется -1, что я считаю более правильным. Почему? Потому что набор
чисел 0 и -1 всегда ведёт себя одинаково что в логических операциях, что в арифметических, а набор 0 и +1 - нет. Это объясняется просто: у числа 0 все биты одинаковые, у -1 - тоже. А как я писал выше, на битовом уровне оба набора операций работают одинаково. У числа же +1 только младший бит 1, остальные - нули, т.е. биты различаются. Реально проблема вылезает только с операцией NOT - отрицание условия / битовая инверсия.
not 0 = -1 (not 00000000b = 11111111b)
not -1 = 0 (not 11111111b = 00000000)
not +1 = -2 (not 00000001b = 11111110b)
Вот тут сишная логика даёт сбой: число -2 не входит в набор (0; -1) и его уже нельзя использовать в
битовых операциях для вычисления
логических выражений.
Эмм, не понял. В смысле "не правильный"? Который?
Он про код на паскале, там 0 не учтён. Самый простой код выглядит так.
if d0 < 0 then d0 := -1 else d0 := 0;
Проще, но не факт, что правильный:
d0 := byte( d0 < 0 );
Тут нужно приведение, потому что в паскале нельзя мешать boolean и числа. На сях можно.
Тут, вероятней всего, -1 / 0 будет использоваться как флаг для дальнейшних CMP, а не для "вычисления сложных логических выражений с использованием битовых операций", т.к. я такого ни разу не видел
Поэтому непонятно, зачем для CMP приводить отрицательное/положительное число к виду -1 / 0, когда можно оставить просто число и проверять после CMP другие флаги:)
По поводу CMP, флагов и сравнения чисел по-человечески (сам всегда путаюсь) глянь эту доку, самый конец:
http://www.zophar.net/fileuploads/2/10541whpzw/68000insset.txt Condition Codes set after CMP D0,D1 Instruction.
Relationship Unsigned Signed
------------ -------- ------
D1 < D0 CS - Carry Bit Set LT - Less Than
D1 <= D0 LS - Lower or Same LE - Less than or Equal
D1 = D0 EQ - Equal (Z-bit Set) EQ - Equal (Z-bit Set)
D1 != D0 NE - Not Equal (Z-bit Clear) NE - Not Equal (Z-bit Clear)
D1 > D0 HI - HIgher than GT - Greater Than
D1 >= D0 CC - Carry Bit Clear GE - Greater than or Equal
PL - PLus (N-bit Clear) MI - Minus (N-bit Set)
VC - V-bit Clear (No Overflow) VS - V-bit Set (Overflow)
RA - BRanch Always