Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: GNU ASSEMBLER
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
ARV
сразу прошу прощения, если не в ту тему: подумалось, что GAS и GCC идут рядом.

вопрос у меня связан с макросами GAS. есть желание сделать макрос автоматически восстанавливающий из стека все, что другой макрос туда запихал. запихивание в стек делаю так:
Код
.altmacro
.macro enter aa:vararg
    push    r0
    in        r0, _SFR_IO_ADDR(SREG)
    push    r0
    .irp p, \aa
        push        p
    .endr
.endm
чтобы сохранить в стеке r0, r1 и r22 использую этот макрос так:
Код
enter r0, r1, r22

аналогичный макрос leave сделал тоже:
Код
.altmacro
.macro leave aa:vararg
.irp p, \aa
    pop        p
.endr
    pop        r0
    out        _SFR_IO_ADDR(SREG), r0
    pop        r0
.endm
однако логично предположить, что если бы строку аргументов мароса enter каким-то образом отреверсить, то в макросе leave можно было бы обойтись без параметров. то есть предположим, каким-то образом во время работы макроса enter создается что-то типа
Код
#define ARG r22, r1, r0
, тогда макрос leave превращается в
Код
.altmacro
.macro leave
.irp p, ARG
    pop        p
.endr
    pop        r0
    out        _SFR_IO_ADDR(SREG), r0
    pop        r0
.endm

вопрос как раз в том, как внутри макроса enter из переданных ему параметров собрать символ с обратным перечнем этих параметров? если суметь сделать такой макрос, то уже никогда не возникнут ошибки с неверным порядком извлечения из стека сохраненных регистров! это одна из распространенных ошибок в ассемблерных программах.
_Pasha
Ну, не знаю... когда я делаю что-то крупное на ассемблере, то организую либо единый пролог-эпилог, либо число этих push/pop настолько мало, что никаких ошибок породить не может. А перевернуть список можно только введя какую-то новую сущность и прогнав текст SED"ом до асма. Как-то сложно это.
ARV
помнится в MASM можно было внутри макроса определять глобальный символ... что-то типа так:
Код
.macro enter aa:vararg
.irp p, \aa
    push        p
   ARGS = p + ',' + ARGS // это то, что я хотел бы сделать !!!
.endr
    push        r0
    in        r0, _SFR_IO_ADDR(SREG)
    push        r0
.endm
и тогда к моменту обращения к макросу leave уже имеем символ ARGS, в котором список аргументов уже в обратном порядке... остается только извлечь их из стека...

только вот никак не могу понять: возможно ли подобным образом в GAS-е сконкатировать аргументы и если возможно, то как это сделать, какие для этого средства есть?
ReAl
Держи, набросал
Порядок регистров в enter не важен, они сортируются и push в прямом, а pop в обратном порядке.

CODE
.nolist
#include <avr/io.h>
.list

.set enter_leave_mask,0

.macro enter aa:vararg
.ifne enter_leave_mask
.error "enter-leave pairing error"
.endif
push r0
in r0, _SFR_IO_ADDR(SREG)
push r0
.ifnb \aa
.irp p, \aa
.set enter_leave_mask, enter_leave_mask | (1 << \p)
.endr
.set i,1 ;; r0 pushed by fixed part
.rept 31
.ifne enter_leave_mask & (1 << i)
push i
.endif
.set i, i+1
.endr
.endif
.endm


.macro leave
.set i,31
.rept 31
.ifne enter_leave_mask & (1 << i)
pop i
.endif
.set i, i-1
.endr
pop r0
out _SFR_IO_ADDR(SREG), r0
pop r0
.set enter_leave_mask, 0
.endm


.text
enter 2,3,5
nop
leave
nop
enter 11,31,0 ; R0 игнорируется, push-нется один раз фиксированной частью
nop
leave
nop
enter
nop
leave
nop
enter 21,3
; enter 22
; leave
leave

rjmp .

.end

avr-gcc -mmcu=atmega8 -c -Wa,-alm=push.lst push.S
avr-objdump -d push.o >push.dump

CODE

push.o: file format elf32-avr


Disassembly of section .text:

00000000 <.text>:
0: 0f 92 push r0
2: 0f b6 in r0, 0x3f ; 63
4: 0f 92 push r0
6: 2f 92 push r2
8: 3f 92 push r3
a: 5f 92 push r5
c: 00 00 nop
e: 5f 90 pop r5
10: 3f 90 pop r3
12: 2f 90 pop r2
14: 0f 90 pop r0
16: 0f be out 0x3f, r0 ; 63
18: 0f 90 pop r0
1a: 00 00 nop
1c: 0f 92 push r0
1e: 0f b6 in r0, 0x3f ; 63
20: 0f 92 push r0
22: bf 92 push r11
24: ff 93 push r31
26: 00 00 nop
28: ff 91 pop r31
2a: bf 90 pop r11
2c: 0f 90 pop r0
2e: 0f be out 0x3f, r0 ; 63
30: 0f 90 pop r0
32: 00 00 nop
34: 0f 92 push r0
36: 0f b6 in r0, 0x3f ; 63
38: 0f 92 push r0
3a: 00 00 nop
3c: 0f 90 pop r0
3e: 0f be out 0x3f, r0 ; 63
40: 0f 90 pop r0
42: 00 00 nop
44: 0f 92 push r0
46: 0f b6 in r0, 0x3f ; 63
48: 0f 92 push r0
4a: 3f 92 push r3
4c: 5f 93 push r21
4e: 5f 91 pop r21
50: 3f 90 pop r3
52: 0f 90 pop r0
54: 0f be out 0x3f, r0 ; 63
56: 0f 90 pop r0
58: 00 c0 rjmp .+0 ; 0x5a <enter_leave_mask+0x5a>


Одно но - регистры надо указывать числами, а не именами R0 и т.д.
Можно под тем .irp сделать ещё один .irp c инкрементом j, котрым перебирать список имён r0,r1,r2,...,r21,R0,R1,R2,...R31 и по .ifeqs если имя из аргумента макроса в списке - устанавливать бит по (1 << (j & 0x1F))
«предоставляется читателю в качестве самостоятельного упражнения»

p.s[0] Эх, и почему я не пишу на ассембелре? Надеюсь, в спорах asm vs C мне не будут говорить, что я на асме не пишу, ибо его не знаю
p.s[1] На PDP-11, MCS-51 у меня подобные макросы бывали...
ARV
ReAl, ну оригинал, ну голова! smile.gif
я-то все про символьные параметры, а тут - ишь! - битовые маски smile.gif
спасибо, буду думать в указанном направлении smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.