Спасибо за подсказку. Работает, хотя наглядность, конечно, при сравнении пропала. Но для уже написанного особой разницы нет.
Вид для печати
Существует ли какой-нибудь метод, который позволяет автоматически развернуть все макросы, подставить все данные и удалить из несработавшие условия?
Исходный макрос:
Код:; LD reg,(IX+d)
macro macro_ld_reg_ix_d reg, data, no_stack
if reg != 0 ; A
ld (.tmp + 1), a
endif
if no_stack == 1 || reg == 5 || reg == 6 ; || H || L
if reg != 5
ld a, h
ld (TMP1 + 1), a
endif
if reg != 6
ld a, l
ld (TMP1), a
endif
else
push hl
endif
ld hl, (rIX)
if reg == 1 || reg == 2 ; B || C
if no_stack == 1
ld a, d
ld (TMP2 + 1), a
ld a, e
ld (TMP2), a
else
push de
endif
ld de, data
else
if no_stack == 1
ld a, b
ld (TMP2 + 1), a
ld a, c
ld (TMP2), a
else
push bc
endif
ld bc, data
endif
if reg == 1 || reg == 2 ; B || C
add hl, de
else
add hl, bc
endif
if reg == 1 || reg == 2 ; B || C
if no_stack == 1
ld a, (TMP2 + 1)
ld d, a
ld a, (TMP2)
ld e, a
else
pop de
endif
else
if no_stack == 1
ld a, (TMP2 + 1)
ld b, a
ld a, (TMP2)
ld c, a
else
pop bc
endif
endif
ld reg, (hl)
if reg == 0 ; A
ld (.tmp + 1), a
endif
if no_stack == 1 || reg == 5 || reg == 6 ; || H || L
if reg != 5
ld a, (TMP1 + 1)
ld h, a
endif
if reg != 6
ld a, (TMP1)
ld l, a
endif
else
pop hl
endif
.tmp ld a, 0
endm
А нужно, чтобы он развернулся, подставились все необходимые значения и убрались все несработавшие условия. То есть, чтобы в итоге в тексте вместо
macro_ld_reg_ix_d A,99-100,0
нарисовалось такое:
Код:; macro_ld_reg_ix_d A,99-100,0
push hl
ld hl, (rIX)
push bc
ld bc, 99-100
add hl, bc
pop bc
ld a, (hl)
pop hl
;---------------------------------------
В общем, отвечаю сам себе, вдруг ещё кому-нибудь пригодится.
1. Создал листинг с помощью ключа --lst
2. Загрузил его в Excel и там разбил на колонки.
3. Удалил следующие строки, удовлетворяющие следующим условиям по двум колонкам:
- Пустой код && >
- Код ~ && >
- Не пустой код && Пустой текст
4. Скопировал колонку с текстом в редактор.
В редакторе дополнительно вручную обработал вызов макросов и локальных меток, которые начинаются с точки.
а потом искать почему неправильно работает, а С то улетел
Я, естественно, сравнил получаемый бинарник до подобного преобразования и после него. Всё совпадает байт в байт.
Я про то что комманда ld R,(ix+D) на афектит флаг С, а замена еще как, да и не только С. Не знаю как часто, но думаю подобные ситуации встречаются.
Не знаю, как вы кавычки пробовали. Вот я попробовал:
Все нормально выполняется. Первое условие выполнилось, второе - нет, все корректно. Хотя я у этого кросс-ассемблера заметил какую-то лажу в приоритетах операций. Иногда довольно странные скобки приходится ставить.Код:macro instr reg1, reg2
if reg1 == "A"
DISPLAY "A"
; some code
if reg2 == "H"
DISPLAY "H"
; some code
endm
instr "A", "C"
Ну и да, у вас второй иф вложен в первый, ENDIFов нет.Код:SjASMPlus Z80 Cross-Assembler v1.21.0 (https://github.com/z00m128/sjasmplus)
Pass 1 complete (0 errors)
Pass 2 complete (0 errors)
> A
macro.asm(11): error: [IF] No ENDIF
macro.asm(15): ^ emitted from here
macro.asm(11): error: [IF] No ENDIF
macro.asm(15): ^ emitted from here
Pass 3 complete
Errors: 2, warnings: 0, compiled: 23 lines, work time: 0.000 seconds
Или вы хотели в instr именно без кавычек писать имена регистров?
Кавычки в параметрах макроса по лексике не подходили.
Видимо просто схематично изобразил условия, ENDIFы в ' ; some code'е спрятались ))
- - - Добавлено - - -
Ну ещё, если не юзать метки, то можно через lua решить вопрос, но телодвижений больше ))
Если честно, вы немного... непонятно формулируете вопрос и свою задачу, мне она не очень понятна. Впечатление, что проблемы именно с формулированием.
Вызов макроса формирует код. В теле макроса у вас выполняются или не выполняются отдельные условия, формируется код, размещенный в сработавших ветвях, код из несработавших ветвей не формируется. Что значит "метод, который позволяет автоматически развернуть все макросы, подставить все данные и удалить из несработавшие условия"? Откуда чего вы хотите удалить?! Я вас не понимать.
Добавил:
и в конце:Код:DEVICE ZXSPECTRUM48
ORG 32768
A EQU 0
(А почему я это должен писать?!)Код:rIX DEFW 0
В итоге, все нормально скомпилировалось, ваш макрос при таком вызове macro_ld_reg_ix_d A,99-100,0 сформировал вот такой код:
И что вы хотите? Поконкретнее плз. Потому чтоКод:PUSH HL
LD HL,(#8012) ; это адрес вашей переменной rIX
PUSH BC
LD BC,#FFFF ; это ваша минус единица, 99-100=-1
ADD HL,BC
POP BC
LD A,(HL)
LD (#8011),A ; это не то, что вы хотели, но таков ваш макрос:
;if reg == 0 ; A
; ld (.tmp + 1), a
;endif
; исправляйте его, если хотите что-то другое
POP HL
LD A,0 ; это тоже не то, что вам нужно, но... вы же это написали в макросе
именно это и произошло.
- - - Добавлено - - -
Какие константы? Это реальные байты. Я не понимаю, зачем использовать для этого реальные байты памяти... Есть переменные. Вон я пример привел с EQU, определил A. Можете теперь сравнивать с A, а не с нулем. Ну вообще конечно плохо пересекаться с именами регистров, но если очень уж хочется, то можно. Но зачем?!
Ну и я просто не вполне понимаю задачу, которую вы делаете. Я так понял, вы хотите реализовать инструкцию работы с индексным регистром, обходясь регистрами HL и BC, этим обеспечив совместимость с другим процессором без поддержки таких инструкций. Вы хотите какие-то исходники преобразовать в такой вот измененный код, переассемблировать, что-то куда-то портировать? На какую машину? Что и откуда вам нужно удалить?!
И да, вам очень правильно указали, что ADD влияет на флаги, в отличие от загрузки в память/из памяти по адресу из индексного регистра плюс-минус смещение, вам придется об этом позаботиться.
Регистры и регистровые пары логичнее было бы нумеровать так, как они пронумерованы в опкодах, чтобы затем по возможности по приходящему значению вычислять нужный опкод, а не городить многоэтажные IFы.
Ну вот я как раз и говорю о том, что у автора вопроса проблемы с формулированием целей и задачи. Чтобы его понять, приходится какое-то время вникать в его макрос, пытаться понять, что он там настроил, да и вообще, что у него в голове за поток сознания, а не просто прочитать комментарий, написанный нормальным языком, мол стоит задача такая-то такая-то, проблема такая-то такая-то.
Посмотрел, что там у Интела с макросами, попробовал написать так же и тут, и это почти заработало, но, поскольку таких имен ни переменных, ни лейблов не существует, там специальный синтаксис для получения значений для сравнения таких вот псевдопеременных из имен регистров, и специальная директива для получения типа входящей переменной, чего в sjasm вроде бы нет. Не помешало бы добавить. Я немного взломал систему, если можно так выразиться, получилось вот так:
Это почти работает, что-то можно сравнивать, но, понятное дело, только с теми регистрами и регистровыми парами, которые умещаются в 16-чную систему счисления. HL, SP, IX, IY, штрихи всякие в пролете. Но это чисто поржать, я не рекомендую так это использовать, т.к. явно тут вылезли какие-то недоработки в компиляторе, которые нужно устранить.Код:macro load8 l8, h8
display $h8
display $l8
ld l8, h8
endm
macro load16 l16, h16
display $h16
display $l16
if $h16 == $AF
display "h16=AF"
endif
if $l16 == $BC
display "l16=BC"
endif
push h16
pop l16
endm
load8 B,C
load16 DE,AF
Ну не знаю, может Ped7g прокомментирует, может быть там есть возможности, о которых мы не знаем.
Upd: Хотя вот так все работает:
Код:B equ 0
C equ 1
D equ 2
E equ 3
H equ 4
L equ 5
A equ 7
b equ 0
c equ 1
d equ 2
e equ 3
h equ 4
l equ 5
a equ 7
BC equ 0
DE equ 1
HL equ 2
SP equ 3
AF equ 3
bc equ 0
de equ 1
hl equ 2
sp equ 3
af equ 3
macro ld8 dst, src
display "LD8"
display src
display dst
if dst == H
display "dst = reg H"
endif
ld dst,src
ld a,b ; это проставит инструкцию с реальными регистрами A и B
endm
ld8 B,C
ld8 H,E
И никаких костылей, или байтов в памяти.Код:SjASMPlus Z80 Cross-Assembler v1.21.0 (https://github.com/z00m128/sjasmplus)
Pass 1 complete (0 errors)
Pass 2 complete (0 errors)
> LD8
> 0x0001
> 0x0000
> LD8
> 0x0003
> 0x0004
> dst = reg H
Pass 3 complete
Errors: 0, warnings: 0, compiled: 208 lines, work time: 0.000 seconds
Я уже всё, что мне нужно сделал. О чём отписался. И, как я понял, на форуме нашлись люди, которые поняли, что что мне требовалось. На всякий случай разъясню ещё раз.
1. Проверки имени регистра в макросе:
Макрос (только для примера!)
Код:macro test reg
if reg == H
ld h, reg
else
ld a, reg
endif
endm
Скомпилироваться должно так:Код:test H
2. По поводу разворачивания макросов. Мне хотелось бы получить текст программы, где на месте всех макросов будут подставлены готовые ассемблерные команды. То есть в тексте программы на месте test H я хотел видеть только ld h, H, без всяких if'ов и прочего.Код:ld h, H
Но, как я написал выше, это уже неактуально.
Оу, ну да, нашлись люди, которые поняли, это я один, такой тупой, непонятливый, все правильно. Но я вам объясняю, что вас понять... трудно, потому что формулируете плохо. Понять-то и я вас понял, но сколько времени на это ушло. У тех людей тоже ушло на это время, просто раньше меня вас прочитали. Сами посмотрите на свой макрос, который вы написали типа для примера. Сколько в нем лишнего мусора, уводящего от сути вопроса. Десять этажей ифов с кучей условий... Ну это банальное неуважение. Сами посмотрите, что вы в ожидании ответа из него написали. Я же не телепат, чтобы угадывать, где вы ошиблись, в макросе, или в описании ожиданий от него. Наверное, найдутся телепаты...
Актуально это для вас, или нет, теперь не важно, раз уж я уже начал с этим ковыряться, и уже нашел решение. Может кому-то будет интересно, будет похожая задача, и он не захочет писать тонну лишнего мусора. Определяем значения переменных:
Макрос:Код:B equ 0
C equ 1
D equ 2
E equ 3
H equ 4
L equ 5
A equ 7
b equ 0
c equ 1
d equ 2
e equ 3
h equ 4
l equ 5
a equ 7
BC equ 0
DE equ 1
HL equ 2
SP equ 3
AF equ 3
bc equ 0
de equ 1
hl equ 2
sp equ 3
af equ 3
ix equ #180
iy equ #280
IX equ #180
IY equ #280
Вызов макроса с разными пограничными значениями:Код:macro ldrx dst,src
push af
push hl
push bc
.iyt equ src-$280 & $FFFF
.ixt equ src-$180 & $FFFF
if src & $200
ld hl,(rIY)
ld bc,.iyt
elseif src & $100
ld hl,(rIX)
ld bc,.ixt
endif
add hl,bc
ld dst,(hl)
pop bc
pop hl
pop af
endm
Все работает. Пожалуйста, вызов - как вы и хотели, даже еще лучше, максимально аутентично. Тут вам и любые регистры на выходе, и сразу оба индексных регистра на входе... Про no_stack стоит забыть, потому что AF необходимо сохранять, сохраняется через стек, как ни крути. Можно добавить проверку на -128-+127 с выбросом ошибки, но мне лень и не надо, сами справитесь.Код:ldrx c,(IX+1)
ldrx a,(IY+1)
ldrx d,(IX-1)
ldrx e,(IY-1)
ldrx h,(IX+127)
ldrx l,(IY+127)
ldrx b,(IX-128)
ldrx d,(IY-128)
rIX DEFW 0
rIY DEFW 0
Можно и имена регистров для проверок использовать, ветвления ассемблирования с этим связанные добавить, но мне, как видите, даже не пригодилось для поставленной задачи. И вот как раз поэтому сложно понять, сложно... Не знаешь никогда, что у другого специалиста в голове, что там за поток, и куда этот поток стремится. Поэтому нужно хотя бы стараться понятным языком излагать свои хотелки, чтобы другие люди не тратили время на расшифровку послания.
- - - Добавлено - - -
Вот вроде такого:
Хотел пошутить, но не буду. Мне вряд ли пригодится. Я даже не понимаю, о чем идет речь, какой-то шифр, а расшифровки нет. И я вряд ли стану ковыряться в Экселе для решения подобных задач. Ну это уже перебор, как по мне. Очевидно, есть другие менее топорные способы:
Файл lst:Код:OPT listmc
Ну тут я, кстати, соглашусь, что не мешало бы настроечку иметь, чтобы метки заменялись на реальные значения, а не тупо копировался код из исходника.Код:# file opened: macro.asm
1 0000 DEVICE ZXSPECTRUM48
2 0000
3 0000 ORG 32768
4 8000
5 8000 OPT listmc
208 8000 41 { ld B,C
208 8001 78 { ld a,b
208 8002 78 { LD A,B
209 8003 63 { ld H,E
209 8004 78 { ld a,b
209 8005 78 { LD A,B
211 8006 F5 { push af
211 8007 E5 { push hl
211 8008 C5 { push bc
211 8009 2A 76 80 { ld hl,(rIX)
211 800C 01 01 00 { ld bc,.ixt
211 800F 09 { add hl,bc
211 8010 4E { ld c,(hl)
211 8011 C1 { pop bc
211 8012 E1 { pop hl
211 8013 F1 { pop af
212 8014 F5 { push af
212 8015 E5 { push hl
212 8016 C5 { push bc
212 8017 2A 78 80 { ld hl,(rIY)
212 801A 01 01 00 { ld bc,.iyt
212 801D 09 { add hl,bc
212 801E 7E { ld a,(hl)
212 801F C1 { pop bc
212 8020 E1 { pop hl
212 8021 F1 { pop af
213 8022 F5 { push af
213 8023 E5 { push hl
213 8024 C5 { push bc
213 8025 2A 76 80 { ld hl,(rIX)
213 8028 01 FF FF { ld bc,.ixt
213 802B 09 { add hl,bc
213 802C 56 { ld d,(hl)
213 802D C1 { pop bc
213 802E E1 { pop hl
213 802F F1 { pop af
214 8030 F5 { push af
214 8031 E5 { push hl
214 8032 C5 { push bc
214 8033 2A 78 80 { ld hl,(rIY)
214 8036 01 FF FF { ld bc,.iyt
214 8039 09 { add hl,bc
214 803A 5E { ld e,(hl)
214 803B C1 { pop bc
214 803C E1 { pop hl
214 803D F1 { pop af
215 803E F5 { push af
215 803F E5 { push hl
215 8040 C5 { push bc
215 8041 2A 76 80 { ld hl,(rIX)
215 8044 01 7F 00 { ld bc,.ixt
215 8047 09 { add hl,bc
215 8048 66 { ld h,(hl)
215 8049 C1 { pop bc
215 804A E1 { pop hl
215 804B F1 { pop af
216 804C F5 { push af
216 804D E5 { push hl
216 804E C5 { push bc
216 804F 2A 78 80 { ld hl,(rIY)
216 8052 01 7F 00 { ld bc,.iyt
216 8055 09 { add hl,bc
216 8056 6E { ld l,(hl)
216 8057 C1 { pop bc
216 8058 E1 { pop hl
216 8059 F1 { pop af
217 805A F5 { push af
217 805B E5 { push hl
217 805C C5 { push bc
217 805D 2A 76 80 { ld hl,(rIX)
217 8060 01 80 FF { ld bc,.ixt
217 8063 09 { add hl,bc
217 8064 46 { ld b,(hl)
217 8065 C1 { pop bc
217 8066 E1 { pop hl
217 8067 F1 { pop af
218 8068 F5 { push af
218 8069 E5 { push hl
218 806A C5 { push bc
218 806B 2A 78 80 { ld hl,(rIY)
218 806E 01 80 FF { ld bc,.iyt
218 8071 09 { add hl,bc
218 8072 56 { ld d,(hl)
218 8073 C1 { pop bc
218 8074 E1 { pop hl
218 8075 F1 { pop af
221 8076 00 00 {rIX DEFW 0
222 8078 00 00 {rIY DEFW 0
# file closed: macro.asm
:v2_dizzy_facepalm: Ну сорян)) И про старуху бывает порнуха) Ну пускай там как-нибудь разрулит эту ситуацию... А мне надо... Идти... )
- - - Добавлено - - -
Не-не-не... У меня железобетонная уважительная причина. Он же сказал, что все порешал, ему ниче не надо. Вот я и выбросил так, как оно есть.)
Но если серьезно, суть моего спича как раз в том и заключается, что ни я, ни кто-либо еще и не должны окунаться в его проблематику с головой, чтобы ответить на простой вопрос, как ему имена регистров использовать. Не так ли?
- - - Добавлено - - -
Upd: Ну ладно... Не оставлять же так, а то совесть замучает, спать спокойно не смогу... Вот вам ваши этажи -)
Вроде все разрулил, теперь все корректно:Код:macro ldrx dst,src
.iyt equ src-$280 & $FFFF
.ixt equ src-$180 & $FFFF
if dst != A
push af
endif
push hl
push bc
if src & $200
ld hl,(rIY)
ld bc,.iyt
elseif src & $100
ld hl,(rIX)
ld bc,.ixt
endif
if dst == A
push af
add hl,bc
pop af
else
add hl,bc
endif
pop bc
if dst == H
ld a,(hl)
pop hl
ld h,a
elseif dst == L
ld a,(hl)
pop hl
ld l,a
else
ld dst,(hl)
pop hl
endif
if dst != A
pop af
endif
endm
Upd: И да, можно написать еще более эффективный макрос, выигрывающий еще какие-то копейки для некоторых вариантов, но зачем мне это публиковать, если все всё уже порешали, а я просто всех раздражаю?! Поэтому пошел я на фиг, ищите сами... -)Код:# file opened: macro.asm
1 0000 OPT listoff
# listing file suspended...
7 8000 OPT reset
8 8000 OPT listmc
241 8000 41 { ld B,C
241 8001 78 { ld a,b
241 8002 78 { LD A,B
242 8003 63 { ld H,E
242 8004 78 { ld a,b
242 8005 78 { LD A,B
244 8006 F5 { push af ;LDRX B|C|D|E|H|L
244 8007 E5 { push hl
244 8008 C5 { push bc
244 8009 2A 78 80 { ld hl,(rIX) ;IX
244 800C 01 01 00 { ld bc,.ixt
244 800F 09 { add hl,bc
244 8010 C1 { pop bc
244 8011 4E { ld c,(hl)
244 8012 E1 { pop hl
244 8013 F1 { pop af
245 8014 E5 { push hl ;LDRX A
245 8015 C5 { push bc
245 8016 2A 7A 80 { ld hl,(rIY) ;IY
245 8019 01 01 00 { ld bc,.iyt
245 801C F5 { push af ;A
245 801D 09 { add hl,bc
245 801E F1 { pop af
245 801F C1 { pop bc
245 8020 7E { ld a,(hl)
245 8021 E1 { pop hl
246 8022 F5 { push af ;LDRX B|C|D|E|H|L
246 8023 E5 { push hl
246 8024 C5 { push bc
246 8025 2A 78 80 { ld hl,(rIX) ;IX
246 8028 01 FF FF { ld bc,.ixt
246 802B 09 { add hl,bc
246 802C C1 { pop bc
246 802D 56 { ld d,(hl)
246 802E E1 { pop hl
246 802F F1 { pop af
247 8030 F5 { push af ;LDRX B|C|D|E|H|L
247 8031 E5 { push hl
247 8032 C5 { push bc
247 8033 2A 7A 80 { ld hl,(rIY) ;IY
247 8036 01 FF FF { ld bc,.iyt
247 8039 09 { add hl,bc
247 803A C1 { pop bc
247 803B 5E { ld e,(hl)
247 803C E1 { pop hl
247 803D F1 { pop af
248 803E F5 { push af ;LDRX B|C|D|E|H|L
248 803F E5 { push hl
248 8040 C5 { push bc
248 8041 2A 78 80 { ld hl,(rIX) ;IX
248 8044 01 7F 00 { ld bc,.ixt
248 8047 09 { add hl,bc
248 8048 C1 { pop bc
248 8049 7E { ld a,(hl) ;H
248 804A E1 { pop hl
248 804B 67 { ld h,a
248 804C F1 { pop af
249 804D F5 { push af ;LDRX B|C|D|E|H|L
249 804E E5 { push hl
249 804F C5 { push bc
249 8050 2A 7A 80 { ld hl,(rIY) ;IY
249 8053 01 7F 00 { ld bc,.iyt
249 8056 09 { add hl,bc
249 8057 C1 { pop bc
249 8058 7E { ld a,(hl) ;L
249 8059 E1 { pop hl
249 805A 6F { ld l,a
249 805B F1 { pop af
250 805C F5 { push af ;LDRX B|C|D|E|H|L
250 805D E5 { push hl
250 805E C5 { push bc
250 805F 2A 78 80 { ld hl,(rIX) ;IX
250 8062 01 80 FF { ld bc,.ixt
250 8065 09 { add hl,bc
250 8066 C1 { pop bc
250 8067 46 { ld b,(hl)
250 8068 E1 { pop hl
250 8069 F1 { pop af
251 806A F5 { push af ;LDRX B|C|D|E|H|L
251 806B E5 { push hl
251 806C C5 { push bc
251 806D 2A 7A 80 { ld hl,(rIY) ;IY
251 8070 01 80 FF { ld bc,.iyt
251 8073 09 { add hl,bc
251 8074 C1 { pop bc
251 8075 56 { ld d,(hl)
251 8076 E1 { pop hl
251 8077 F1 { pop af
254 8078 00 00 {rIX DEFW 0
255 807A 00 00 {rIY DEFW 0
# listing file suspended...
# file closed: macro.asm
varargs for macro are mentioned few times in various issues, like: https://github.com/z00m128/sjasmplus/issues/150
You are welcome to check current proposal/notes and add any new suggestion/syntax detail so it's not lost when finally somebody will want to work on it.
(I'm currently working very little at hobby stuff, too busy with newborn, work and running/fitness, ZX dev time shrink to few hours per month right now)
- - - Updated - - -
There's no good native support for what you are trying to do.
You can maybe hack it by doing DEFINE with numeric values, ie. DEFINE A 1 : DEFINE REG_A 1 : IF reg1 == REG_A ... but it will probably bite you badly in other ways because the defines like "A" are too short and generic. Other possible hack is to use lua script to check for value of macro argument reg1, that's less intrusive, but cumbersome.
Mind you, sjasmplus has the i8080 support the other-way, ie. you can write i8080 code in Zilog syntax and the assembler will warn you when you use Z80-specific instruction by accident. sjasmplus has also support for "M" register as `(hl)` alias.
You can add to source code:
and assemble it with --i8080 switch to get results like this:Код:; use --i8080 switch to 8080 instructions only
OPT --syntax=M ; enable "M" register as (hl) alias
LD A,B ; MOV A,B
LD A,M ; MOV A,M
LDIR ; error "Unrecognized instruction: LDIR"
But to do it the other way, ie. to support original i8080 syntax, you should probably look for other assembler, sjasmplus is not a good choice for that.Код:$ sjasmplus --i8080 --msg=lstlab -
; use --i8080 switch to 8080 instructions only
OPT --syntax=M ; enable "M" register as (hl) alias
LD A,B ; MOV A,B
LD A,M ; MOV A,M
LDIR ; error "Unrecognized instruction: LDIR"
# file opened: <stdin>
1 0000 ; switch to 8080 instructions only
2 0000 OPT --syntax=M
3 0000 78 LD A,B ; MOV A,B
4 0001 7E LD A,M ; MOV A,M
<stdin>(5): error: Unrecognized instruction: LDIR
5 0002 LDIR ; error "Unrecognized instruction: LDIR"
6 0002
# file closed: <stdin>
Есть константы
iBlue = %00000001
pYellow = %00110000
Есть макрос, который вызывается как
Если вызывать его какКод:MacroName arg1, arg2
в код передается значение #2A (%00101010)Код:MacroName (iBlue + pYellow), arg2
Если вызывать его как
в код передается ожидаемое (по крайней мере, для меня), значение #31 (%00110001).Код:MacroName iBlue + pYellow, arg2
Почему?
О как...
yes, macro arguments are text-substituted before the macro line is parsed, evaluated and assembled.
So `ld a, arg1` will become `ld a, (iBlue + iYellow)` and that will access memory from address #31 (ROM).
To avoid the similar issues like C macros have, you want to use macro arguments more like:
`ld a, +(arg1)` -> `ld a, +((iBlue + iYellow))` -> `ld a,#31`
Having parentheses around arguments in expressions helps to avoid stuff like:
BTW when in doubt, try listing (--lst --lstlab). You may see the macro lines somewhat substituted there, quick example trying to mimic your question:Код:macro m1 arg1, arg2
ld a, arg1 * arg2
ld a, +(arg1) * (arg2)
endm
m1 4<<2, 1+2
; ->
; ld a, 4<<2*1+2 -> ld a, #40 ; 4 << (2*1+2) -> 4 << 4 -> 64
; ld a, +(4<<2)*(1+2) -> ld a, #30 ; 16 * 3 -> 48
does produce this when using stdin as input and --msg=lst option:Код:macro m1 arg1, arg2
ld a, arg1
ld a, +(arg1)
endm
iBlue = %00000001
pYellow = %00110000
m1 (iBlue + pYellow), 123
; btw "=" are not constants but "variables" or DEFL, so you can still modify them later, constants are EQU
iBlue = %00000010 ; check next result
m1 (iBlue + pYellow), 123
So by reading the listing file you have chance to spot unexpected bytes/instructions or evaluation results.Код:$ sjasmplus --msg=lst -
macro m1 arg1, arg2
ld a, arg1
ld a, +(arg1)
endm
iBlue = %00000001
pYellow = %00110000
m1 (iBlue + pYellow), 123
; btw "=" are not constants but "variables" or DEFL, so you can still modify them later, constants are EQU
iBlue = %00000010 ; check next result
m1 (iBlue + pYellow), 123
# file opened: <stdin>
1 0000 macro m1 arg1, arg2
2 0000 ~ ld a, arg1
3 0000 ~ ld a, +(arg1)
4 0000 endm
5 0000 iBlue = %00000001
6 0000 pYellow = %00110000
7 0000 m1 (iBlue + pYellow), 123
7 0000 3A 31 00 > ld a, (iBlue + pYellow)
7 0003 3E 31 > ld a, +((iBlue + pYellow))
8 0005 ; btw "=" are not constants but "variables" or DEFL, so you can still modify them later, constants are EQU
9 0005 iBlue = %00000010 ; check next result
10 0005 m1 (iBlue + pYellow), 123
10 0005 3A 32 00 > ld a, (iBlue + pYellow)
10 0008 3E 32 > ld a, +((iBlue + pYellow))
11 000A
# file closed: <stdin>