Closed Volutar closed 5 years ago
Тут проблема разбивается на две части:
Если это режим "трассировки", то метки в принципе не нужно рисовать, пока трассировка не остановится. Куча этих доп.сравнений и отражений меток нужна только для ручного хождения по коду.
Задача непростая, но если она будет сделана - получится безусловно лучший дизасм, на уровне, а то и выше IDA.
Сложность в том, что дизасм знает только о том, что он показывает. Остальное для него - "куча каких-то байт". Между делом, метка может указывать не только на код. Это может быть ascii-строка, внутри которой что-то меняется. Это может быть "DW слово", у которого меняют старший байт...
Эти ассемблерные структуры, к сожалению, недоступны. Внутрь структур или строк, с каким-то конкретным известным типом данных (как в том же IDA) - это задача как бы совсем другого уровня, и хранить как-то всю эту кухню, или каждый раз генерировать - гемор. Логичнее тут просто смотреть в радиусе 3х байт относительно ссылаемого адреса (условно) имеющиеся метки. Брать ближайшую в этом радиусе, и на неё ссылаться со сдвигом. Это как вариант решения (1).
А на вариант (2) - только во время отображения детектить что метка попадает внутрь, и не отображается, и рисовать её отдельной строкой, добавляя строчку с EQU. Проще - ниже, в виде equ $-N. Но наверное, можно и выше. Просто если этого не делать, то в дебаггере, в зависимости от кодестайла, будет немало меток, отсылка на которые есть, а увидеть их нельзя - они слева просто никогда не будут отображаться.
Оба варианта будут работать "не всегда". Если метка изначально ссылается внутрь команды, то никакого сдвига относительно неё не будет. А с equ - обратный эффект. Если обращение было через (label + n), то никакой метки внутри команды не будет, мы будем иметь слово, которое может быть как адресом, так и просто каким-то числом. См пример: 0x8001 тут вообще не start+1
org 0x8000
start:
......
; и тут где-то встречается
ld hl,0x8001
and 7
ret z
lab:
rr h
rl l
dec a
jr nz,lab
ret
А если там будет ld hl,0x8000, не связанный с адресом, он вместо него подставит start? Это же точно также будет неправильно, как и в случае 0x8001. Речь же не просто о вордах, а об операторах с прямой адресацией, иначе это надо анализатор кода какой-то делать - об этом речи нет.
Что-то проклюнулось
Нифига себе :) Круто! Ну это кейс №2, когда метка существует, и она указывает внутрь команды. Но кейс №1 - когда метка указывает на саму команду, но отсылка идёт со смещением. Тут лично я не вижу никаких иных способов, кроме как включать в метку сдвиговый параметр, если адрес оператора входит в диапазон от -3 до +3 (макс. длина оператора 4 - и это уже по-идее должна быть другая метка). Ну и это только для тех операторов, которые не просто загрузка регистров, а прямая работа с памятью (ld r/rr,(N) и ld (N),r/rr). Возможно и ещё какие-то операторы, но по своему опыту это просто хранения переменных внутри самого кода в параметрах, и впихивание их по прямым адресам.
Подумалось, что этот параметр min/max можно конфигуряемым сделать . У меня допустим есть структуры где метка на начало а длина 12 байт, и было бы неплохо чтобы все отсылки внутрь неё шли по метка+смещение.
Метка ищется на 4 байта назад
Как вариант: для кода область действия - длина команды, для остальных - 8 байт
Это же чисто визуальный хелпер, тут не будет вреда если сделать "радиус" настраиваемым (и в плюс и в минус).
В моём коде PSM вообще бывают Label-13 (тут как бы можно просто любой адрес интерпретировать как ближайшая_метка +- смещение). Это же касательно операторов типа LD reg,(addr) или LD (addr),reg, но не LD HL,value. Загрузка данных в регистр лично для меня вообще не должна отсылаться к меткам, даже если она +0. Интерпретация каждого значения #FFFF как метки, в случае наличия метки по этому адресу, чревато кучей мест, когда вывод этих значений как метки в 99% случаев будет ошибочным.
Это безусловно прискорбно, что просто 16разрядные значения EQU, и 16разрядные адреса меток - не имеют никакого признака для того чтобы их отличать.
Хотя, можно было бы принять какое-то соглашение о префиксах, чтобы эту таблицу меток интерпретировать более красиво. Например, если название метки начинается с символа _, то это не адрес. Можно было бы это даже сделать в опциях. Назвать поле например "const label prefixes", и если оно задано, интерпретировать все 16разрядные значения, совпадающие со значениями меток с таким префиксом, как метки, даже если это LD DE,#8004. Разрешить целый ряд этих префиксов, через запятую, мало ли как бывает.
Примерно такие мысли.
Но вообще выглядит уже зашибенски :) С такими фишками этот "на коленках писанный дебаггер" существенно удобнее всех имеющихся.
Очень часто код - самомодифицируемый. То есть вида:
onetime1: ld a,1 and a jr z,label2 xor a ld (onetime+1),a label2: ....
Хотелось бы, чтобы отсылки внутрь инструкций также работали. Либо через смещение в адресации (если метка указывает ровно на саму инструкцию), либо через добавление строки типа:
ld a,1 onetime: equ $-1 ... ld (onetime),a
либо
onetime: equ $+1 ld a,1 ... ld (onetime),a
если метка указывает внутрь инструкции.