Estoy tratando de compilar el siguiente programa de ensamblaje simple, pero hay un problema con el compilador que no puedo encontrar el motivo y solucionarlo.
Así que aquí está el código:
1 #define __SFR_OFFSET 0
2 #include <avr/io.h>
3
4
5 rjmp Init
6
7 .global Init
8
9 Init: sbi _SFR_IO_ADDR(PORTB),5
10 rjmp In
y cuando voy a compilarlo con
avr-as -c -mmcu=atmega168a -o ledON.o ledON.s
Estoy recibiendo este error:
ledON.s: Assembler messages:
ledON.s:9: Error: constant value required
ledON.s:9: Error: `,' required
ledON.s:9: Error: constant value required
ledON.s:9: Error: garbage at end of line
También cambio un poco el código como se puede ver arriba, pero todavía hay un error
1 ;#define _SFR_OFFSET 0
2 #include <avr/io.h>
3
4 rjmp Init
5
6 .global Init
7
8 Init: sbi PORTB,0x05
9 rjmp Init
ledON.s: Mensajes del ensamblador:
ledON.s:8: Error: valor constante requerido
¿Algunas ideas?
Descubrí cómo ensamblar sin mensajes de error.
Los mensajes de error que ve se deben al hecho de que avr-as
no invoca el preprocesador C y, por lo tanto, las #include
líneas se leen como comentarios normales.
Cree un archivo ledON.S
y observe las MAYÚSCULAS S
en el nombre del archivo. La mayúscula S
indica que primero se debe invocar el preprocesador C. Cree el archivo con el siguiente contenido:
#include <avr/io.h>
init: sbi _SFR_IO_ADDR(DDRB),0x05 ; Configure port B pin 5 as output
ret
.global main
main:
call init
loop:
sbi _SFR_IO_ADDR(PORTB),0x05 ; Toggle output pin HIGH
cbi _SFR_IO_ADDR(PORTB),0x05 ; Toggle output pin LOW
rjmp loop
La main
parte se requiere en el código fuente, aquí es donde generalmente se encuentra el programa principal. Si lo elimina, nunca se ejecuta ningún código real y, por lo tanto, el compilador se quejará de eso. El código de una rutina llamada init
debe llamarse explícitamente desde main
. Aunque el pin cambia, en la práctica esto será demasiado rápido para verlo a simple vista. Si verifica con un osciloscopio, verá una onda cuadrada (estimo en un ciclo de trabajo del 25%).
Luego ensamble el código fuente con:
avr-gcc -mmcu=atmega168a ledON.S -o ledON.o
Nuevamente avr-gcc
se requiere invocar el preprocesador C.
Para verificar el resultado del programa ensamblado, ejecute el siguiente comando:
avr-objdump -C -d ./ledON.o
Y la lista de desmontaje resultante se ve así:
./ledON.o: file format elf32-avr
Disassembly of section .text:
00000000 <__vectors>:
0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end>
4: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
8: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
10: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
14: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
18: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
1c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
20: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
24: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
28: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
2c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
30: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
34: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
38: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
3c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
40: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
44: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
48: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
4c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
50: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
54: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
58: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
5c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
60: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
64: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt>
00000068 <__ctors_end>:
68: 11 24 eor r1, r1
6a: 1f be out 0x3f, r1 ; 63
6c: cf ef ldi r28, 0xFF ; 255
6e: d4 e0 ldi r29, 0x04 ; 4
70: de bf out 0x3e, r29 ; 62
72: cd bf out 0x3d, r28 ; 61
74: 0e 94 42 00 call 0x84 ; 0x84 <main>
78: 0c 94 47 00 jmp 0x8e ; 0x8e <_exit>
0000007c <__bad_interrupt>:
7c: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>
00000080 <init>:
80: 25 9a sbi 0x04, 5 ; 4
82: 08 95 ret
00000084 <main>:
84: 0e 94 40 00 call 0x80 ; 0x80 <init>
00000088 <loop>:
88: 2d 9a sbi 0x05, 5 ; 5
8a: 2d 98 cbi 0x05, 5 ; 5
8c: fd cf rjmp .-6 ; 0x88 <loop>
0000008e <_exit>:
8e: f8 94 cli
00000090 <__stop_program>:
90: ff cf rjmp .-2 ; 0x90 <__stop_program>
INTERMEZZO
Notará que el ensamblador inicializará automáticamente el puntero de la pila y el registro de estado en
__ctors_end
. También agregará automáticamente unarjmp
al final del código. El comportamiento predeterminado de un programa ensamblado por gcc-avr cuando finaliza es:
- desactivar las interrupciones (
_exit
,cli
)- bucle vacío infinito que no hace nada (
__stop_program
,rjmp .-2
)
ledON.S: Assembler messages: ledON.S:8: Error: number must be positive and less than 32
tales errores creo que eso significa que el registro de E/S no es editable.rjmp
. La main
etiqueta es una parte requerida del programa, si la elimina, recibirá un mensaje de error. Normalmente ahí es donde se encuentra el programa principal.avr-gcc
llama .avr-as
yippie
avr-as
estás usando, la mía no es compatible con la-c
bandera, qué hace?FN
-c
la bandera, obtengo el mismo error: syippie
FN
yippie