-
- ? Дмитрий
- 11.03.2019 17:38
Каким образом вы учитываете вывод через DDraw при перемещении окна, когда туда производится рисование? Я, когда городил вывод, коснулся DDraw чуток и забросил - как раз из-за вывода в указанный участок экрана при перемещении окна. Окно утащили, а вывод продолжается на место бывшего окна.
- ? Дмитрий
- 11.03.2019 14:09
Пишите эмуляцию напрямую в асме - будет быстро. Эмуляция вещь затратная.
- ? Дмитрий
- 11.03.2019 13:47
>> выпилить MFC, обойтись VCL
Все рано все сводится к виндовым controls - MFC/VCL всего лишь обертки
¤
>> потом по кускам как нибуть реверснуть на Дельфу...
Реверснуть надо саму эмуляцию, а все остальное можно сделать и самому - это гораздо проще эмуляции. Кстати, я так и сделал, ибо интерфейс проще с нуля написать, чем конвертить обертки.
- ? Дмитрий
- 11.03.2019 01:21
>> эмуляция EIS проходит тест 791402
А есть где эти тесты в исходниках?
- ? Дмитрий
- 10.03.2019 12:17
Благодарю. Кстати, а simh проходит тесты eis/fis? Качнул исходники, там довольно лаконично сэмулировано. Только непонятно, почему остаток от деления не получен через %.
- ? Дмитрий
- 08.03.2019 21:50
Непонятка с DIV. Судя по описанию знак результата совпадает со знаком делимого. Но 27 / -3 = -9, а согласно описанию должно будет получиться 9. Команду сначала реализовал на IDIV, но сейчас закрались сомнения - а верно ли? Есть соображения как правильно ее реализовать на асме?
- ? Дмитрий
- 17.02.2019 23:44
>> менее 4Кб для таблицы разделов
Для десятки это вообще бессмысленно. А для 11(М) еще худо-бедно. Есть доп. память БК и СМК, хотя ее тоже по факту маловато.
¤
>> Кроме ОС БК (с шаманством с BY.SYS) и МКДОС даже 32Мб никто не поддерживает.
Тут простор для написания новой ДОС, хотя бы с FAT16.
- ? Дмитрий
- 14.02.2019 17:36
>> Начать надо с переделки драйвера дисковода
Копать яму чайной ложкой? Ну ок. Проще переделать СМК на поддержку LBA и переделать формат хранения таблицы разделов. Только ни это, ни обход ограничения в 127 дорожек никому не нужны, ибо уже давно бы сделали.
- ? Дмитрий
- 10.02.2019 15:19
Ну и добавить работу с LBA
- ? Дмитрий
- 10.02.2019 15:18
>> Для БК не получится разметить более 20Гб
Переделать формат хранения таблицы разделов и все
- ? Дмитрий
- 10.02.2019 12:42
У меня такой на 160Гб от iPod'а валяется рабочий. Но у него разъем пленочный. На али купил переходник на IDE. И тоже была мысля засунуть его в SMK.
- ? Дмитрий
- 10.02.2019 12:40
Что-то запамятовал я по поводу XOR. Она в асме пишется как XOR R2,R1 (код 074201), т.е. R1=R2 xor R1. А непосредственную константу нельзя использовать, как, к примеру, в MUL/DIV, где в асме меняются местами операнды? Или там тот же принцип XOR #1,R2 (код 074227 000001)?
- ? Дмитрий
- 01.02.2019 23:12
https://zx-pk.ru/threads/14785-russkij-ttf-shrift-kak-na-spektrume.html там шрифт спека, с русскими буквами
- ? Дмитрий
- 28.01.2019 14:41
Кстати, эмуль OPL3, который я хочу попробовать прикрутить, вообще не оперирует частотой девайса. Там используется только его родная частота дискретизации 49716Гц. Так что для упрощения можно привязать проц с этой частоте (и вообще все звуковые буферы), потому как мешать звук, допустим, Ковокса на 44100 со звуком OPL3 на 49176 получится каша.
¤
>> Там надо как-то умудриться сделать независимые потоки
Вот у меня та же мысля. Поток проца работает независимо от других, но! Он для доступа к памяти использует глобальную interlock-переменную (я пока сделал так, ибо позднее, если дойдут руки, сделаю маппинг/блиттинг). И все потоки, которые должны обращаться к памяти, также должны ее использовать. А это можно сделать написав, к примеру, "внеклассные" единые для всех SetByte/SetWord с передачей не только внутреннего адреса и данных, но и адреса памяти БК. В них перед записью в память проверяется interlock-переменная на 0, далее она лочится и только в этом случае данные пишутся в память с поледующей разлочкой переменной. Либо написать эти функции на асме, юзая префикс LOCK с XCHG - в регистр EAX помещаем адрес в памяти, в DX - записываемое значение и пишем его в память с залочкой шины: LOCK XCHG word ptr[EAX],DX или LOCK XCHG byte ptr[EAX],DL. Все остальные потоки, обратившись к этой же ячейке в тот же момент, "замерзнут" на этой команде до окончания ее выполнения. В итоге любое кол-во потоков будут корректно юзать память без критических ситуаций. Или сделать в каждом классе-потоке свои SetByte/SetWord точно таким же способом.
¤
Но! Если внимательно рассмотреть ситуацию, то все это не нужно, ибо пишет в память только класс и поток проца. Видеоконтроллер только читает. Звуковой класс имеет свои буферы. Системные порты реализованы в виде переменных. А читать из одной и той же ячейки можно сколь угодно большому числу потоков. Все потоки привязать к работающему потоку проца. m_lockExecuteFrame проверять ВСЕМ потокам и работать только в случае его активности. Останов проца выполнять в паузах между фреймами и все остальные потоки суспендить (они стоят на проверке m_lockExecuteFrame). Если возникла нештатная ситуация, то выполнить останов со сбросом m_lockExecuteFrame в 0, а после обработки останова m_lockExecuteFrame=1 и поехали дальше. Как-то так...
- ? Дмитрий
- 28.01.2019 11:09
Что-то я не пойму всей фишки синхронизации со звуком. Возьмем абстрактный проц с частотой X МГц. Есть звуковой чип с частотой Y МГц и частотой дискретизации 44100Гц. Все остальное пока отбросим. В итоге каждые Y*10^6/44100 тактов мы должны получить от чипа данные двух каналов и передать их в буфер. По заполнению буфера передать их на воспроизведение, а пока заниматься заполнением другого буфера.
¤
SoundSampleRate = Y*1000000 / 44100
¤
1) Проверяем - не наступило ли время выполнения очередной инструкции?
2) Да - выполняем инструкцию, получаем время ее исполнения в тактах, нет - увеличиваем число тактов проца на 1, уменьшаем число тактов прошлой выполненной инструкции на 1
3) Выполняем NextTick класса эмуляции звукового чипа (там он увеличивает число своих тактов на 1 и проверяет - не насчитали ли число тактов SoundSampleRate? Да - рендерим каналы и прочее, нет - выходим).
4) уходим на п.1
¤
И к чему мы тут привязываемся? К частоте звукового чипа? А получается привязаться к частоте проца можно только фреймами. Или есть какой-то другой способ привязки?
¤
И еще непонятно, почему в реализации YM2149 частота взята
¤
#define EMU_SOUNCHIP_FREQUENCY 3428572 //BK: (12Mhz / 7) * 2
¤
в 2 раза больше, чем реальная? А период в тактах вычислен вообще от max Integer?
- ? Дмитрий
- 24.01.2019 23:00
Тьфу, соврал. cmpxchg она юзает.
- ? Дмитрий
- 24.01.2019 22:59
Можно и ее. Но XCHG требует использования еще одного операнда, а INC/DEC одного. Кстати InterlockerExchange как раз ее и юзает.
- ? Дмитрий
- 24.01.2019 22:27
LOCK гарантирует, что только один поток будет иметь доступ к ячейке на запись.
- ? Дмитрий
- 24.01.2019 21:23
>> и тут мы приходим к пониманию, чем симулятор отличается от эмулятора.
Да тут не важно - симулятор или эмулятор. Я сферически говорю. А в моем случае можно сделать так, чтобы генератор "останавливался" перед выполнением команды (фактически вызов TranslateInstruction), по возврату к счетчику прибавляется время в тактах выполненной команды (мы же затратили время). Ну и далее проверки - надо ли было кому-то что-то сделать. Генератор объединить с таймером, чтобы убрать лишний поток.
¤
>> нужен точный потактовый эмулятор процессора
А для этого нужны все точные растактовки для каждой команды (коих нет, только "на глазок" измеренные), для каждого метода адресации, для чтения/записи памяти.
¤
>> можно сделать эмуляцию всего в одном потоке
В принципе можно, но с ростом частоты погрешность будет увеличиваться.
¤
-----
Кстати, этот InterlockerExchange и класс под него - расточительство. Я сделал так (не совсем понимаю как на Си написать):
¤
var
MemLock: dword; // вместо класса LockVarType
¤
procedure Lock(var LockVar: dword); assembler; // адрес переменной будет в EAX
asm
@1:
CMP [EAX],0
JNZ @1
LOCK INC [EAX]
end;
¤
procedure Unlock(var LockVar: dword);
begin
LockVar:=0; // или LOCK DEC [EAX]
end;
¤
и все. Все отлично работает (проверено), не надо специально проверять в цикле переменную на !=0 для залочки. Просто Lock(переменная) в нужном месте и Unlock(переменная).
- ? Дмитрий
- 24.01.2019 17:59
>> синхронизировать генерируемый звук с реальным временем
Т.е. 6МГц/44100Гц = ~136 тактов, получается, что каждые 136 тактов я должен записать в звуковой буфер 2 сэмпла (L+R) и по заполнению буфера проиграть его, а заполнять следующий. И, следовательно, таким же образом рассчитать через сколько тактов я должен буду вывести 1 строку изображения на экран, через сколько тактов "тикнуть" таймером и т.д. и т.п. Но вся фигня в том, что все эти действия нужно выполнять одновременно, иначе все поедет из-за неравномерного времени выполнения эмуляции команд. Тут я вижу только один вариант. Сделать главный поток "тактового генератора", которому на старте передать через сколько тактов делать вывод звука, сработка таймера, вывод строки изображения (или одной точки) и т.д. Все эти вспомогательные потоки запускаются, но ждут разлочки каждый своей переменной. А "генератор" сам разлочит нужную через определенный промежуток. Но "тикание" генератора - тупое увеличение переменной на 1 + несколько проверок не нужно ли кому выполнить свою часть работы. А эмуляция команды может выполняться дольше числа тактов, отведенных на нее. В результате генератор "утикает" дальше, чем число тактов и получится рассинхрон.
- ? Дмитрий
- 24.01.2019 14:53
>> Синхронизация делается по звуку
Что-то я тогда не пойму - как вообще эта синхронизация работает, если звук, допустим, выводится с частотой 44100, а проц, к примеру, 6МГц? Каким образом будет синхронизация выполнения команд, если эмуляция выполняется на частоте хост-проца?
- ? Дмитрий
- 24.01.2019 10:22
2 gid: Эмулятор GameBoy https://habr.com/ru/post/154901/ - никаких таймеров/задержек, частота эмулируемого проца используется только для вычисления в звуковой части SamplePeriod, все выполняется на скорости хост-проца. Гляньте на досуге, мб какие мысли придут. Ссыль на гитхаб есть в статье.
- ? Дмитрий
- 16.01.2019 13:28
Код на верилоге (или на Си) - помню, читал. Там мрак. Хоть и Си-подобный, но черт ногу сломит. А есть уже эта модель в коде, отличном от верилога? Я уже неоднократно думал убрать к чертям это поддержание частоты 100МГц, убрать фреймы и "запустить" проц на макс. возможную частоту, которую может дать эмуляция на хост-процессоре. Тогда не надо будет синхронизироваться с тактами эмуляции команд. К тому же я так и не придумал как обойти эмуляцию индекса на гибком диске.
¤
В качестве звукового чипа хочу прицепить эмулятор Nuked OPL3 Алексея Хохлова, который в инете считают едва ли не самым лучшим и точным. Но есть только модуль, а как его использовать (с какой частотой снимать данные с рендера каналов для заполнения звукового буфера) - примеров не нашел. Писал ему в ЛС на тюбике, но он не ответил.
¤
И еще. У таймера 42,9 мкс это полный цикл с множителем х1 и начальной константой 0? Расчетый получается 42,66 мкс. У 11(М) на 4Мгц ровно 32 мкс.
- ? Дмитрий
- 16.01.2019 11:40
Я все никак не могу допереть - как сделать синхронное "тикание" тактов и выполнение инструкций (вернее синхронный учет затраченных тактов на выполнение)? Ведь во время выполнения инструкции таймер продолжает считать, тактовый генератор тоже не ждет проц, движок дисковода продолжает вращаться и т.д. Хоть там и микроскопические задержки, но все равно так неправильно. Максимум пока что пришло в голову - разнести выполнение инструкций и таймер со счетчиком тактов в разные потоки. Счетчик тактов работает только во время выполнения инструкций (ExecuteFrame). Но как синхронизировать это все? Если один поток считает такты и там же: учитывается таймер, медиа-такты и пр. В данном случае счет будет независим от выполнения. Но! Допустим выполняется инструкция и ее "время" 10 тактов, которое мы получим уже после выполнения. Поток с таймером и счетчиком тактов продолжает свою работу во время выполнения. По идее надо считать значение счетчика тактов до выполнения инструкции, выполнить инструкцию, прибавить время выполнения команды и ждать в счетчике полученного значения. Но счетчик тактов считает на полной скорости хостового проца и, скорее всего, счетчик давно пройдет эти 10 тактов. А дальше... дальше мысль обрывается...
- ? Дмитрий
- 08.01.2019 23:31
блин... вечно путаюсь в этих равно-не равно. Все верно...
- ? Дмитрий
- 08.01.2019 23:30
И далее надо не установить 7 бит в 177660, а сбросить его. В итоге:
¤
//если ещё прошлый код не прочитали, новый игнорируем.
if ((board->m_reg177660 & 0200) != 0)
{
//сюда заходим только если прочитан прошлый код
board->m_reg177662in = nScanCode & 0177;
board->m_reg177660 &= ~0200;
board->KeyboardInterrupt((vkbdvw->isAR2Press()) ? INTERRUPT_274 : nInt);
}
- ? Дмитрий
- 08.01.2019 21:51
Не пойму почему так: в CBKView::EmulateKeyDown есть строки
¤
//если ещё прошлый код не прочитали, новый игнорируем.
if ((board->m_reg177660 & 0200) == 0)
¤
но в описании регистра 177660 говорится, что бит7=1 означает, что в 177662 есть код и надо его считать и при его наличии нажатия игнорируются до сброса. Т.е. по описанию должно быть if ((board->m_reg177660 & 0200) != 0).
- ? Дмитрий
- 24.12.2018 01:55
Что-то мне склероз уже изменяет: на БК читались данные по 0хEC, а потом переворачивались все или переворачивались только строки с моделью и т.п.?. А то в CHDD::configure() из служебного сектора читается конфигурация образа
¤
m_nCylinders = m_pSectorBuffer.w[1];
m_nHeads = m_pSectorBuffer.w[3];
m_nSectors = m_pSectorBuffer.w[6];
¤
и данные берутся без swab. Получается, в служебном секторе .hdi (и у винта) только текстовые данные перевернуты, а числовые нет?
- ? Дмитрий
- 21.12.2018 17:15
С LBA48 я тогда разобрался по спецификации, непонятка была именно с чтением регистров 1F3-1F5. Бит HOB нужен для чтения содержимого этих регистров. Согласно спецификации при HOB=1 читается старшая часть регистра, при =0 - соответственно младшая. Запись в регистр осуществляется байтами (при любой записи в регистры HOB сбрасывается) и предыдущее значение сдвигается в старшую часть Reg_1F5 = (Reg_1F5 << 8) | NewByte. Т.е. сколько раз в регистр не пиши - запомнены будут последние два байта.
- ? Дмитрий
- 21.12.2018 14:48
Я не про исходники эмуля, а про исходники прошивки SMK - там напортачено.
- ? Дмитрий
- 21.12.2018 00:34
Возник вопрос по процедурам SMK в плане чтения/записи HDD. Какой умник написал так, что проверка на ошибку НЕ производится сразу ПОСЛЕ подачи команды считывания/записи данных, а выполняется после считывания самих данных? Имхо это неверно. Ведь если произошла ошибка, допустим, позиционирования или отсуствия маркера, то будет выставлен бит соответствующей ошибки. Или попадется битый сектор, попытки считывания закончатся и опять-таки выставится бит ERROR. А п/п тупо ждет сброса бита BUSY, а затем ждет выставления бита готовности данных и при его наличии выполняет чтение. А получается, что читать-то нечего - голова не дошла по адресу сектора (или сектор битый), BUSY сброшен, а бита готовности данных нет и не будет. Правильнее будет подать команду, выждать сброс бита BUSY, проверить бит ERROR и только после его отсутствия проверять бит наличия данных и читать оные. А в прошивке имхо бред.
- ? Дмитрий
- 15.12.2018 00:39
Что-то не въеду в логику работы 48-битной адресации в плане чтения регистров. В доках ATA6 указано, что при 8-битных регистрах можно использовать регистры 1F2-1F5 как 16-битные путем "текущей" и "предыдущей" записи. Т.е., как я понял, для задания кол-ва читаемых/записываемых секторов более 256 пишем в регистр 1F2 сначала старшие 8 бит и следом младшие 8 бит. Точно также и с адресом LBA сектора в регистрах 1F3-1F5. Так вот чтение этих данных производится при манипуляции бита HOB (7-й бит регистра 1F7, т.е. командного регистра). Выставленный в 1 он дасти прочитать из 1F2-1F5 старшие части, а при HOB=0 - младшие. Но как его выставить - ведь это же командный регистр? Нельзя же просто взять и записать в 1F7 значение 0x80.
¤
А в доках АТА8 никакие HOB не указывается и не описываются, а говорится, что регистры для LBA уже 16-битные. Плюс непонятно, как устройство может выполнять 32 битный I/O, если регистр данных 16-битный?
- ? Дмитрий
- 03.12.2018 17:08
В CHDD::configure проверяется служебный сектор на валидность.
¤
BYTE cs = 0;
for (int i = 0; i < 511; ++i)
{
cs += m_pSectorBuffer.b[i];
}
cs = -cs;
¤
В чем смысл cs = -cs, если BYTE беззнаковый тип?
- ? Дмитрий
- 16.11.2018 11:18
>> Я когда его хакал, убрал только защиту от копирования
А в чем состояла защита? Как работала?
- ? Дмитрий
- 23.10.2018 22:59
Есть же TRDCOPY - она понимает диски спека (чтение, поиск спрайтов). Образ .trd переименовать в img или dsk и "подключить" в дисковод.
- ? Дмитрий
- 14.10.2018 00:39
2 BD: А что за исправленная прошивка СМК? Что там исправлено?
- ? Дмитрий
- 09.10.2018 14:21
С ASHC разобрался, все в норме. Наткнулся еще на одну неточность в описании команды DIV. В описании сказано, что "V устанавливается, если источник (делитель) равен нулю, либо если значение регистра по модулю больше абсолютной величины делителя: в этом случае деление не выполняется, поскольку результат выйдет за разрядную сетку." Это неверно. При таком делении ДЕЛИТЕЛЬ не должен быть больше делимого, а не наоборот.
¤
MOV #25.,R0
CLR R1
DIV #5,R0 ; 25/5
¤
получится 5, хотя по описанию R0 > 5, а значит переполнение. Разве нельзя нацело разделить 25 на 5 без переполнения? А вот наоборот 5/25 - даже знаковый DIV интела вызывает ошибку переполнения. Кстати, "по модулю" равнозначно "абсолютная величина".
- ? Дмитрий
- 04.10.2018 13:35
тьфу, gcc сует ASHC #-1
- ? Дмитрий
- 04.10.2018 13:33
В дополнение к ASH. Есть простейший алгоритм формирования таблицы для подсчета CRC32.
¤
unsigned long crc_table[256];
¤
void make_crc_table()
{
for ( unsigned long i = 0; i < 256; i++ )
{
unsigned long r = i;
for ( unsigned long j = 0; j < 8; j++ )
{
if (r & 1)
r = (r >> 1) ^ 0xEDB88320;
else
r >>= 1;
}
crc_table[i] = r;
}
}
¤
pdp11-gcc для сдвига вставляет ASH #-1 для реализации SHR, что неверно - SHR логический сдвиг, а ASH арифметический. Оставим это на совести gcc. Так вот, переведя его на асм, столкнулся с проблемкой, а именно - если ASH реализовать на х86 SAL/SAR (полный аналог ASL/ASR), то таблица формируется неверно (во всех 256 значениях самый старший байт в тетраде неправильный, а остальные 3 правильные - налицо баги сдвига, как раз 8 бит). Если же SAL/SAR заменить в реализации ASH на SHL/SHR (для проверки), то алгоритм работает как часы и таблица формируется абсолютно верно. Хорошо. Убрал ASH и сделал связку CLC+ROR (по сути тот же SHR) - сдвиг вправо с очисткой самого старшего бита. Однако таблица опять неверна - опять самый старший байт тетрады неверный. Полез в реализацию ROR (взята из эмулятора gid'а) - все верно, реализация правильная. Для очистки совести заменил на асм-реализацию:
¤
...
mov cl,byte ptr[SignC] // берем текущий признак С из булевой переменной (0 - false, 1 - true)
rcr cl // выталкиваем бит 0 во флаг CF
rcr eax // крутим данные, вталкивая из CF в 31 бит EAX и вытесняя 0 бит в CF (ROR)
... // далее тащим в признаки новые значения из флагов х86
¤
поскольку перед ROR я делаю CLC, то SignC всегда false (cl=0) и после "rcr cl" CF всегда 0. Однако алгоритм опять не работает и опять старший байт тетрады результата неверный. Причем он отличается от того, который получен в реализации ROR gid'а.
¤
Первый элемент равен 0
¤
верное значение 2 элемента: 0x77073096
ROR (вариант gid'а): 0x09073096
ROR (asm-вариант с RCR): 0xF5073096
- ? Дмитрий
- 02.10.2018 09:22
Кстати, в коде в gid - 29.09.2018 09:36 последние две строки справедливы для ПРАВОГО сдвига, ибо результат будет в МЛАДШЕЙ части, а для ЛЕВОГО результат будет в СТАРШЕЙ части. Поэтому запись результата нужна отдельно для каждого сдвига.
- ? Дмитрий
- 02.10.2018 09:05
Упустил момент с одинаковыми частями при нечетном регистре. Да, получается чистый интеловский ROL/ROR. Отлично, фактически еще одна команда в пределах другой.
- ? Дмитрий
- 01.10.2018 21:10
>> получается не просто PDPшный ROR, ROL. А настоящий циклический сдвиг, почти такой, как на интеловском х86, когда бит С не участвует в сдвиге, а только отображает разряд, вытесненный из регистра.
Покрутил я ASHC. Как раз и выходит, что с нечетным регистром получается как раз ПДПшный ROL/ROR. Интеловский ROL/ROR крутит биты внутри, когда вытесняемый бит попадает одновременно в признак CF и в конец/начало. ПДПшным ROL/ROR полностью соответствует интеловские RCR/RCL, которые крутят биты через CF. Так вот крутить двойное слово надо парами команд SAL/SAR (соответствует ПДПшным ASL/ASR) + RCL/RCR. Сначала смещаем арифметическим сдвигом первую часть, выталкивая бит в признак CF, а затем, крутя вторую половину двойного слова, мы вытесненный бит заводим во вторую часть и выталкиваем в CF бит из второй же. А ROL/ROR будет вытесненный бит крутить внутри второй части, что неверно. И при нечетном регистре получится как раз в финале RCL/RCR.
- ? Дмитрий
- 01.10.2018 13:08
Я уже накидал на асме реализацию ASH - жаль в х86 при занесении данных в регистр не выставляются флаги по результату, пришлось добавлять test для этого. Обошлось без сдвигов на 1 меньше и прочего. Получилось коротко и просто. Щас ASHC сделаю по тому же принципу.
- ? Дмитрий
- 01.10.2018 11:13
>> Мне, например, лень мешает
Лень - двигатель прогресса, но не в этом случае. :) Мне мешает закопанные в кладовке телек (монитор) и БК10. Плюс надо все это где-то собрать, вспомнить на каких дискетах есть дос да модуль арифметический.
¤
Про сдвиг я понял, просто в описании не описан левый сдвиг (даже в официальных handbook'ах), а только правый.
- ? Дмитрий
- 29.09.2018 00:12
В описании сказано, что:
¤
Содержимое регистра, и регистра с номером, полученным установкой младшего бита в номере указанного регистра, рассмаиривается как одно 32 - битовое слово, причем в регистре с большим номером содержатся младшие биты, а регистре с меньшим - старшие, дигается влево или вправо на число позиций, указанное счетчике сдвига. Счетчиком сдвига являются младшие 6 бит операнда-источника. Отрицательное значение счетчика вызывает сдвиг вправо, положительное - влево. Если номер регистра-приемника нечетный, правый сдвиг становится вращением. 16-разрядное слово вращается вправо на число позиий, указанное в счетчике сдвига. При правом сдвиге распространяется старший бит, при левом сдвиге младший бит грузится нулем. V устанавливается, если при сдвиге изменялся знак операнда, иначе очищается; c загружается последним выдвинутым из 32-битового операнда битом.
¤
Непонятка во фразе "Если номер регистра-приемника нечетный, правый сдвиг становится вращением. 16-разрядное слово вращается вправо на число позиий, указанное в счетчике сдвига." Т.е., емнип, двухрегистровый ASHC превращается в однорегистровый ROR с регулилируемым кол-вом сдвигов. А если регистр нечетный и сдвиг указан влево? Будет ROL или ничего не будет? По идее ROL, но кто его знает - походу описание неполное.
- ? Дмитрий
- 20.09.2018 17:19
Это нормально, что у обоих файлов 410(8) байт с начала забито нулями?
- ? Дмитрий
- 17.09.2018 09:19
А что в этом мониторе такого особенного? Для чего он был предназначен?
- ? Дмитрий
- 13.07.2018 13:16
Нашел в masm32 реализацию FloatToStr - коротко и понятно
- ? Дмитрий
- 12.07.2018 22:15
Я откинул ПДПшный формат, взял IEEE754. Раз сделал FPU, то обязательно нужна упаковка/распаковка. Упаковка простая, а вот распаковка мне не по зубам. Кстати, вот что значит давно не программить на асме - привык ко всему готовому, низкоуровневые операции в голове отсуствуют.
- ? Дмитрий
- 12.07.2018 13:22
Собсна сабж. Почитал исходники Вильнюсского Бейсика - там вообше ни черта непонятно. Какой алгоритм распаковки и упаковки используется для сабжа (интересует именно IEEE754, PDPшный 32-битный формат float совпадает, а double неактуален)? У меня есть только распаковка числа в фиксированном формате, нужен экспоненциальный. Порылся в glibc - там нагромождение какое-то без каких-либо комментов.
-
«
1 | 2 | 3 | 4 | 5 | ... | 9 | »
?