Извините, я всю тему не смог осилить.
Начинал я когда-то давно на MACRO-11, надо сказать мне сильно повезло, это был 'правильный' ассемблер и там сразу была заложена концепция локальных меток как в тексте программы так и в макросредствах. Поэтому эта концепция прочно засела у меня в голове и использование в инструкциях аргументов типа PC+смещение (.+смещение, $+смещение и прочее) воспринимается, мягко говоря, странно.
Потом был Борландовский TASM, также прекрасно поддерживающий локальные метки. А вот потом пошли всякие i51, 8080, Фуджитцы, AVR (лень все перечислять - как архитектуры так и ассемблеры) и я начал сильно страдать. Если бОльшая часть ассемблеров еще как-то поддерживала локальные метки в макросах, то собственно в коде с этими метками была беда. Вот тогда пришла идея написать препроцессор локальных меток. Идея самая заурядная - в коде выделяются границы блоков локальных меток (по первому символу строки - если символ может принадлежать имени обычной (нелокальной) метки - то граница блока) и в пределах этого блока все слова с определенным префиксом (в TASM это было "@@", но можно взять любое понравившееся сочетание) заменяются на такое же слово но с удаленным префиксом и с добавленным числовым суффиксом. Таким образом локальные метки становятся общими и уникальными для текущего файла.
Пример, исходный текст
CODE
Int_UART_STxD: push R23 ;
push R17 ;
lds R23,SP_Flags ;
sbrc R23,SNFl_RXoff ;
rjmp @@SendXOFF ;
sbrc R23,SNFl_RXon ;
rjmp @@SendXON ;
sbrc R23,SNFl_Xoff ;
rjmp @@ReadyTxd ;
;
lds R16,SP_DrvEnd ;
lds R17,SP_DrvBeg ;
cp R16,R17 ;
breq @@ReadyTxd ;
push Z1 ;
push Z0 ;
mov Z0,R16 ;
clr Z1 ;
subi Z0,low(-SP_DrvBuf) ;
sbci Z1,high(-SP_DrvBuf) ;
ld R17,Z+ ;
out UDR,R17 ;
pop Z0 ;
pop Z1 ;
inc R16 ;
cpi R16,TBufSiz ;
brlo @@Wrapup ;
clr R16 ;
@@Wrapup: sts SP_DrvEnd,R16 ;
;
@@Exit: sts SP_Flags,R23 ;
pop R17 ;
pop R23 ;
pop R16 ;
out SREG,R16 ;
pop R16 ;
reti ;
;
@@ReadyTxd: cbi UCR,UDRIE ;
rjmp @@Exit ;
;
@@SendXOFF: cbr R23,(1<<SNFl_RXoff) ;
ldi R16,_XOFF ;
out UDR,R16 ;
rjmp @@Exit ;
;
@@SendXON: cbr R23,(1<<SNFl_RXon) ;
ldi R16,_XON ;
out UDR,R16 ;
rjmp @@Exit ;
Текст после препроцессора:
CODE
Int_UART_STxD: push R23 ;
push R17 ;
lds R23,SP_Flags ;
sbrc R23,SNFl_RXoff ;
rjmp SendXOFF_0058 ;
sbrc R23,SNFl_RXon ;
rjmp SendXON_0059 ;
sbrc R23,SNFl_Xoff ;
rjmp ReadyTxd_0060 ;
;
lds R16,SP_DrvEnd ;
lds R17,SP_DrvBeg ;
cp R16,R17 ;
breq ReadyTxd_0060 ;
push Z1 ;
push Z0 ;
mov Z0,R16 ;
clr Z1 ;
subi Z0,low(-SP_DrvBuf) ;
sbci Z1,high(-SP_DrvBuf) ;
ld R17,Z+ ;
out UDR,R17 ;
pop Z0 ;
pop Z1 ;
inc R16 ;
cpi R16,TBufSiz ;
brlo Wrapup_0061 ;
clr R16 ;
Wrapup_0061: sts SP_DrvEnd,R16 ;
;
Exit_0062: sts SP_Flags,R23 ;
pop R17 ;
pop R23 ;
pop R16 ;
out SREG,R16 ;
pop R16 ;
reti ;
;
ReadyTxd_0060: cbi UCR,UDRIE ;
rjmp Exit_0062 ;
;
SendXOFF_0058: cbr R23,(1<<SNFl_RXoff) ;
ldi R16,_XOFF ;
out UDR,R16 ;
rjmp Exit_0062 ;
;
SendXON_0059: cbr R23,(1<<SNFl_RXon) ;
ldi R16,_XON ;
out UDR,R16 ;
rjmp Exit_0062 ;
Пишем и редактируем исходный код, а ассемблеру подсовываем результат препроцессора.
Позже препроцессор оброс еще всякими полезными функциями - преобразование табуляций, удаление комментариев (недавно особенно хорошо было отрубать букву 'я' в комментах для IAR-ского кортексовского ассемблера). В-общем, программа 15 лет в строю и зарекомендовала себя как универсальный инструмент с десятком разных ассемблеров. Изначально была написана на TASM для MS-DOS, но недавно Win7 отказался запускать .com файл - пришлось переписать под Win32. Если кому-то интересно - то архив с исходниками этой крошечной утилиты в аттаче. Там же проект и уже готовая собранная утилита.
Нажмите для просмотра прикрепленного файла