¿Hay un desensamblador AVR que produce una salida legible para el ser humano, por ejemplo, escribe
OUT SREG,R0
en lugar de
OUT 0x3F,R0
(Me gustaría comprender mejor lo que está haciendo el compilador)
¿Hay un desensamblador AVR que produce una salida legible para el ser humano, por ejemplo, escribe
OUT SREG,R0
en lugar de
OUT 0x3F,R0
(Me gustaría comprender mejor lo que está haciendo el compilador)
Lamento revivir este hilo, pero me he preguntado algunas veces cómo podría tener avr-objdump
de salida de nombres de registro adecuados. Descubrí que es inútil. ¿O es eso? ¡No para un amante de los pitones, por supuesto!
Esa es la razón de este script, que básicamente es un contenedor / post-procesador para avr-objdump
. Actualmente está limitado a unas pocas arquitecturas, a saber, avr35
y avr5
esencialmente porque usé esos 3 procesadores: ATmega64M1 , ATmega328 (Arduino) y ATtiny1634 . Hay espacio para mejorar, como hacer que la lista de registro esté disponible en módulos, pero esto abre el camino.
La invocación de la línea de comandos es tan simple como esto:
adump.py <MCUNAME> <avr-objdump arguments>
Ejemplos:
adump.py atmega328 -S main.flash.hex
Si tiene la imagen flash binaria sin procesar que ha descargado de una pizarra:
adump.py atmega328 -D -b binary main.flash.bin
Aquí está la salida para una imagen flash recuperada de un programa simple de parpadeo escrito para el ATmega64M1:
$ adump.py atmega64m1 -D -b binary blink-m64m1.bin
...
00000000 <.data>:
0: 0c 94 3e 00 jmp 0x7c ; 0x7c
4: 0c 94 48 00 jmp 0x90 ; 0x90
8: 0c 94 48 00 jmp 0x90 ; 0x90
c: 0c 94 48 00 jmp 0x90 ; 0x90
10: 0c 94 48 00 jmp 0x90 ; 0x90
14: 0c 94 48 00 jmp 0x90 ; 0x90
18: 0c 94 48 00 jmp 0x90 ; 0x90
1c: 0c 94 48 00 jmp 0x90 ; 0x90
20: 0c 94 48 00 jmp 0x90 ; 0x90
24: 0c 94 48 00 jmp 0x90 ; 0x90
28: 0c 94 48 00 jmp 0x90 ; 0x90
2c: 0c 94 48 00 jmp 0x90 ; 0x90
30: 0c 94 48 00 jmp 0x90 ; 0x90
34: 0c 94 48 00 jmp 0x90 ; 0x90
38: 0c 94 48 00 jmp 0x90 ; 0x90
3c: 0c 94 48 00 jmp 0x90 ; 0x90
40: 0c 94 48 00 jmp 0x90 ; 0x90
44: 0c 94 48 00 jmp 0x90 ; 0x90
48: 0c 94 48 00 jmp 0x90 ; 0x90
4c: 0c 94 48 00 jmp 0x90 ; 0x90
50: 0c 94 48 00 jmp 0x90 ; 0x90
54: 0c 94 48 00 jmp 0x90 ; 0x90
58: 0c 94 48 00 jmp 0x90 ; 0x90
5c: 0c 94 48 00 jmp 0x90 ; 0x90
60: 0c 94 48 00 jmp 0x90 ; 0x90
64: 0c 94 48 00 jmp 0x90 ; 0x90
68: 0c 94 48 00 jmp 0x90 ; 0x90
6c: 0c 94 48 00 jmp 0x90 ; 0x90
70: 0c 94 48 00 jmp 0x90 ; 0x90
74: 0c 94 48 00 jmp 0x90 ; 0x90
78: 0c 94 48 00 jmp 0x90 ; 0x90
7c: 11 24 eor r1, r1
7e: 1f be out SREG, r1 ; 63
80: cf ef ldi r28, 0xFF ; 255
82: d0 e1 ldi r29, 0x10 ; 16
84: de bf out SPH, r29 ; 62
86: cd bf out SPL, r28 ; 61
88: 0e 94 4a 00 call 0x94 ; 0x94
8c: 0c 94 5a 00 jmp 0xb4 ; 0xb4
90: 0c 94 00 00 jmp 0 ; 0x0
94: 82 e0 ldi r24, 0x02 ; 2
96: 8a b9 out DDRD, r24 ; 10
98: 92 e0 ldi r25, 0x02 ; 2
9a: 8b b1 in r24, PORTD ; 11
9c: 89 27 eor r24, r25
9e: 8b b9 out PORTD, r24 ; 11
a0: 2f e3 ldi r18, 0x3F ; 63
a2: 3d e0 ldi r19, 0x0D ; 13
a4: 83 e0 ldi r24, 0x03 ; 3
a6: 21 50 subi r18, 0x01 ; 1
a8: 30 40 sbci r19, 0x00 ; 0
aa: 80 40 sbci r24, 0x00 ; 0
ac: e1 f7 brne .-8 ; 0xa6
ae: 00 c0 rjmp .+0 ; 0xb0
b0: 00 00 nop
b2: f3 cf rjmp .-26 ; 0x9a
b4: f8 94 cli
b6: ff cf rjmp .-2 ; 0xb6
Ahora aquí está el script, con la esperanza de que aún sea útil:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# adump.py
#
# Copyright 2017 Nasha
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
from __future__ import print_function
import sys
def report(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
arches = {
# List of supported architectures.
# See http://www.atmel.com/webdoc/AVRLibcReferenceManual/using_tools_1using_avr_gcc_mach_opt.html
# for updates
"at90s1200": "avr1",
"attiny11": "avr1",
"attiny12": "avr1",
"attiny15": "avr1",
"attiny28": "avr1",
"at90s2313": "avr2",
"at90s2323": "avr2",
"at90s2333": "avr2",
"at90s2343": "avr2",
"attiny22": "avr2",
"attiny26": "avr2",
"at90s4414": "avr2",
"at90s4433": "avr2",
"at90s4434": "avr2",
"at90s8515": "avr2",
"at90c8534": "avr2",
"at90s8535": "avr2",
"at86rf401": "avr25",
"ata6289": "avr25",
"ata5272": "avr25",
"ata6616c": "avr25",
"attiny13": "avr25",
"attiny13a": "avr25",
"attiny2313": "avr25",
"attiny2313a": "avr25",
"attiny24": "avr25",
"attiny24a": "avr25",
"attiny25": "avr25",
"attiny261": "avr25",
"attiny261a": "avr25",
"attiny4313": "avr25",
"attiny43u": "avr25",
"attiny44": "avr25",
"attiny44a": "avr25",
"attiny441": "avr25",
"attiny45": "avr25",
"attiny461": "avr25",
"attiny461a": "avr25",
"attiny48": "avr25",
"attiny828": "avr25",
"attiny84": "avr25",
"attiny84a": "avr25",
"attiny841": "avr25",
"attiny85": "avr25",
"attiny861": "avr25",
"attiny861a": "avr25",
"attiny87": "avr25",
"attiny88": "avr25",
"atmega603": "avr3",
"at43usb355": "avr3",
"atmega103": "avr31",
"at43usb320": "avr31",
"at90usb82": "avr35",
"at90usb162": "avr35",
"ata5505": "avr35",
"ata6617c": "avr35",
"ata664251": "avr35",
"atmega8u2": "avr35",
"atmega16u2": "avr35",
"atmega32u2": "avr35",
"attiny167": "avr35",
"attiny1634": "avr35",
"at76c711": "avr3",
"ata6285": "avr4",
"ata6286": "avr4",
"ata6612c": "avr4",
"atmega48": "avr4",
"atmega48a": "avr4",
"atmega48pa": "avr4",
"atmega48p": "avr4",
"atmega8": "avr4",
"atmega8a": "avr4",
"atmega8515": "avr4",
"atmega8535": "avr4",
"atmega88": "avr4",
"atmega88a": "avr4",
"atmega88p": "avr4",
"atmega88pa": "avr4",
"atmega8hva": "avr4",
"at90pwm1": "avr4",
"at90pwm2": "avr4",
"at90pwm2b": "avr4",
"at90pwm3": "avr4",
"at90pwm3b": "avr4",
"at90pwm81": "avr4",
"at90can32": "avr5",
"at90can64": "avr5",
"at90pwm161": "avr5",
"at90pwm216": "avr5",
"at90pwm316": "avr5",
"at90scr100": "avr5",
"at90usb646": "avr5",
"at90usb647": "avr5",
"at94k": "avr5",
"atmega16": "avr5",
"ata5790": "avr5",
"ata5702m322": "avr5",
"ata5782": "avr5",
"ata6613c": "avr5",
"ata6614q": "avr5",
"ata5790n": "avr5",
"ata5795": "avr5",
"ata5831": "avr5",
"atmega161": "avr5",
"atmega162": "avr5",
"atmega163": "avr5",
"atmega164a": "avr5",
"atmega164p": "avr5",
"atmega164pa": "avr5",
"atmega165": "avr5",
"atmega165a": "avr5",
"atmega165p": "avr5",
"atmega165pa": "avr5",
"atmega168": "avr5",
"atmega168a": "avr5",
"atmega168p": "avr5",
"atmega168pa": "avr5",
"atmega169": "avr5",
"atmega169a": "avr5",
"atmega169p": "avr5",
"atmega169pa": "avr5",
"atmega16a": "avr5",
"atmega16hva": "avr5",
"atmega16hva2": "avr5",
"atmega16hvb": "avr5",
"atmega16hvbrevb": "avr5",
"atmega16m1": "avr5",
"atmega16u4": "avr5",
"atmega32": "avr5",
"atmega32a": "avr5",
"atmega323": "avr5",
"atmega324a": "avr5",
"atmega324p": "avr5",
"atmega324pa": "avr5",
"atmega325": "avr5",
"atmega325a": "avr5",
"atmega325p": "avr5",
"atmega325pa": "avr5",
"atmega3250": "avr5",
"atmega3250a": "avr5",
"atmega3250p": "avr5",
"atmega3250pa": "avr5",
"atmega328": "avr5",
"atmega328p": "avr5",
"atmega329": "avr5",
"atmega329a": "avr5",
"atmega329p": "avr5",
"atmega329pa": "avr5",
"atmega3290": "avr5",
"atmega3290a": "avr5",
"atmega3290p": "avr5",
"atmega3290pa": "avr5",
"atmega32c1": "avr5",
"atmega32hvb": "avr5",
"atmega32hvbrevb": "avr5",
"atmega32m1": "avr5",
"atmega32u4": "avr5",
"atmega32u6": "avr5",
"atmega406": "avr5",
"atmega64rfr2": "avr5",
"atmega644rfr2": "avr5",
"atmega64": "avr5",
"atmega64a": "avr5",
"atmega640": "avr5",
"atmega644": "avr5",
"atmega644a": "avr5",
"atmega644p": "avr5",
"atmega644pa": "avr5",
"atmega645": "avr5",
"atmega645a": "avr5",
"atmega645p": "avr5",
"atmega6450": "avr5",
"atmega6450a": "avr5",
"atmega6450p": "avr5",
"atmega649": "avr5",
"atmega649a": "avr5",
"atmega6490": "avr5",
"atmega6490a": "avr5",
"atmega6490p": "avr5",
"atmega649p": "avr5",
"atmega64c1": "avr5",
"atmega64hve": "avr5",
"atmega64hve2": "avr5",
"atmega64m1": "avr5",
"m3000": "avr5",
"at90can128": "avr51",
"at90usb1286": "avr51",
"at90usb1287": "avr51",
"atmega128": "avr51",
"atmega128a": "avr51",
"atmega1280": "avr51",
"atmega1281": "avr51",
"atmega1284": "avr51",
"atmega1284p": "avr51",
"atmega128rfr2": "avr51",
"atmega1284rfr2": "avr51",
"atmega2560": "avr6",
"atmega2561": "avr6",
"atmega256rfr2": "avr6",
"atmega2564rfr2": "avr6",
"atxmega16a4": "avrxmega2",
"atxmega16a4u": "avrxmega2",
"atxmega16c4": "avrxmega2",
"atxmega16d4": "avrxmega2",
"atxmega32a4": "avrxmega2",
"atxmega32a4u": "avrxmega2",
"atxmega32c3": "avrxmega2",
"atxmega32c4": "avrxmega2",
"atxmega32d3": "avrxmega2",
"atxmega32d4": "avrxmega2",
"atxmega8e5": "avrxmega2",
"atxmega16e5": "avrxmega2",
"atxmega32e5": "avrxmega2",
"atxmega64a3": "avrxmega4",
"atxmega64a3u": "avrxmega4",
"atxmega64a4u": "avrxmega4",
"atxmega64b1": "avrxmega4",
"atxmega64b3": "avrxmega4",
"atxmega64c3": "avrxmega4",
"atxmega64d3": "avrxmega4",
"atxmega64d4": "avrxmega4",
"atxmega64a1": "avrxmega5",
"atxmega64a1u": "avrxmega5",
"atxmega128a3": "avrxmega6",
"atxmega128a3u": "avrxmega6",
"atxmega128b1": "avrxmega6",
"atxmega128b3": "avrxmega6",
"atxmega128c3": "avrxmega6",
"atxmega128d3": "avrxmega6",
"atxmega128d4": "avrxmega6",
"atxmega192a3": "avrxmega6",
"atxmega192a3u": "avrxmega6",
"atxmega192c3": "avrxmega6",
"atxmega192d3": "avrxmega6",
"atxmega256a3": "avrxmega6",
"atxmega256a3u": "avrxmega6",
"atxmega256a3b": "avrxmega6",
"atxmega256a3bu": "avrxmega6",
"atxmega256c3": "avrxmega6",
"atxmega256d3": "avrxmega6",
"atxmega384c3": "avrxmega6",
"atxmega384d3": "avrxmega6",
"atxmega128a1": "avrxmega7",
"atxmega128a1u": "avrxmega7",
"atxmega128a4u": "avrxmega7",
"attiny4": "avrtiny10",
"attiny5": "avrtiny10",
"attiny9": "avrtiny10",
"attiny10": "avrtiny10",
"attiny20": "avrtiny10",
"attiny40": "avrtiny10",
}
regs = {
# Register dictionary for supported architectures
"avr35": {
0x7F : "TWSCRA",
0x7E : "TWSCRB",
0x7D : "TWSSRA",
0x7C : "TWSA",
0x7B : "TWSAM",
0x7A : "TWSD",
0x79 : "UCSR1A",
0x78 : "UCSR1B",
0x77 : "UCSR1C",
0x76 : "UCSR1D",
0x75 : "UBRR1H",
0x74 : "UBRR1L",
0x73 : "UDR1",
0x72 : "TCCR1A",
0x71 : "TCCR1B",
0x70 : "TCCR1C",
0x6F : "TCNT1H",
0x6E : "TCNT1L",
0x6D : "OCR1AH",
0x6C : "OCR1AL",
0x6B : "OCR1BH",
0x6A : "OCR1BL",
0x69 : "ICR1H",
0x68 : "ICR1L",
0x67 : "GTCCR",
0x66 : "OSCCAL1",
0x65 : "OSCTCAL0B",
0x64 : "OSCTCAL0A",
0x63 : "OSCCAL0",
0x62 : "DIDR2",
0x61 : "DIDR1",
0x60 : "DIDR0",
0x3F : "SREG",
0x3E : "SPH",
0x3D : "SPL",
0x3C : "GIMSK",
0x3B : "GIFR",
0x3A : "TIMSK",
0x39 : "TIFR",
0x38 : "QTCSR",
0x37 : "SPMCSR",
0x36 : "MCUCR",
0x35 : "MCUSR",
0x34 : "PRR",
0x33 : "CLKPR",
0x32 : "CLKSR",
0x30 : "WDTCSR",
0x2F : "CCP",
0x2E : "DWDR",
0x2D : "USIBR",
0x2C : "USIDR",
0x2B : "USISR",
0x2A : "USICR",
0x29 : "PCMSK2",
0x28 : "PCMSK1",
0x27 : "PCMSK0",
0x26 : "UCSR0A",
0x25 : "UCSR0B",
0x24 : "UCSR0C",
0x23 : "UCSR0D",
0x22 : "UBRR0H",
0x21 : "UBRR0L",
0x20 : "UDR0",
0x1F : "EEARH",
0x1E : "EEARL",
0x1D : "EEDR",
0x1C : "EECR",
0x1B : "TCCR0A",
0x1A : "TCCR0B",
0x19 : "TCNT0",
0x18 : "OCR0A",
0x17 : "OCR0B",
0x16 : "GPIOR2",
0x15 : "GPIOR1",
0x14 : "GPIOR0",
0x13 : "PORTCR",
0x12 : "PUEA",
0x11 : "PORTA",
0x10 : "DDRA",
0x0F : "PINA",
0x0E : "PUEB",
0x0D : "PORTB",
0x0C : "DDRB",
0x0B : "PINB",
0x0A : "PUEC",
0x09 : "PORTC",
0x08 : "DDRC",
0x07 : "PINC",
0x06 : "ACSRA",
0x05 : "ACSRB",
0x04 : "ADMUX",
0x03 : "ADCSRA",
0x02 : "ADCSRB",
0x01 : "ADCH",
0x00 : "ADCL",
},
"avr5": {
0xFA : "CANMSG",
0xF9 : "CANSTMPH",
0xF8 : "CANSTMPL",
0xF7 : "CANIDM1",
0xF6 : "CANIDM2",
0xF5 : "CANIDM3",
0xF4 : "CANIDM4",
0xF3 : "CANIDT1",
0xF2 : "CANIDT2",
0xF1 : "CANIDT3",
0xF0 : "CANIDT4",
0xEF : "CANCDMOB",
0xEE : "CANSTMOB",
0xED : "CANPAGE",
0xEC : "CANHPMOB",
0xEB : "CANREC",
0xEA : "CANTEC",
0xE9 : "CANTTCH",
0xE8 : "CANTTCL",
0xE7 : "CANTIMH",
0xE6 : "CANTIML",
0xE5 : "CANTCON",
0xE4 : "CANBT3",
0xE3 : "CANBT2",
0xE2 : "CANBT1",
0xE1 : "CANSIT1",
0xE0 : "CANSIT2",
0xDF : "CANIE1",
0xDE : "CANIE2",
0xDD : "CANEN1",
0xDC : "CANEN2",
0xDB : "CANGIE",
0xDA : "CANGIT",
0xD9 : "CANGSTA",
0xD8 : "CANGCON",
0xD2 : "LINDAT",
0xD1 : "LINSEL",
0xD0 : "LINIDR",
0xCF : "LINDLR",
0xCE : "LINBRRH",
0xCD : "LINBRRL",
0xCC : "LINBTR",
0xCB : "LINERR",
0xCA : "LINENIR",
0xC9 : "LINSIR",
0xC8 : "LINCR",
0xBC : "PIFR",
0xBB : "PIM",
0xBA : "PMIC2",
0xB9 : "PMIC1",
0xB8 : "PMIC0",
0xB7 : "PCTL",
0xB6 : "POC",
0xB5 : "PCNF",
0xB4 : "PSYNC",
0xB3 : "POCR_RBH",
0xB2 : "POCR_RBL",
0xB1 : "POCR2SBH",
0xB0 : "POCR2SBL",
0xAF : "POCR2RAH",
0xAE : "POCR2RAL",
0xAD : "POCR2SAH",
0xAC : "POCR2SAL",
0xAB : "POCR1SBH",
0xAA : "POCR1SBL",
0xA9 : "POCR1RAH",
0xA8 : "POCR1RAL",
0xA7 : "POCR1SAH",
0xA6 : "POCR1SAL",
0xA5 : "POCR0SBH",
0xA4 : "POCR0SBL",
0xA3 : "POCR0RAH",
0xA2 : "POCR0RAL",
0xA1 : "POCR0SAH",
0xA0 : "POCR0SAL",
0x97 : "AC3CON",
0x96 : "AC2CON",
0x95 : "AC1CON",
0x94 : "AC0CON",
0x92 : "DACH",
0x91 : "DACL",
0x90 : "DACON",
0x8B : "OCR1BH",
0x8A : "OCR1BL",
0x89 : "OCR1AH",
0x88 : "OCR1AL",
0x87 : "ICR1H",
0x86 : "ICR1L",
0x85 : "TCNT1H",
0x84 : "TCNT1L",
0x82 : "TCCR1C",
0x81 : "TCCR1B",
0x80 : "TCCR1A",
0x7F : "DIDR1",
0x7E : "DIDR0",
0x7C : "ADMUX",
0x7B : "ADCSRB",
0x7A : "ADCSRA",
0x79 : "ADCH",
0x78 : "ADCL",
0x77 : "AMP2CSR",
0x76 : "AMP1CSR",
0x75 : "AMP0CSR",
0x6F : "TIMSK1",
0x6E : "TIMSK0",
0x6D : "PCMSK3",
0x6C : "PCMSK2",
0x6B : "PCMSK1",
0x6A : "PCMSK0",
0x69 : "EICRA",
0x68 : "PCICR",
0x66 : "OSCCAL",
0x64 : "PRR",
0x61 : "CLKPR",
0x60 : "WDTCSR",
0x3F : "SREG",
0x3E : "SPH",
0x3D : "SPL",
0x37 : "SPMCSR",
0x35 : "MCUCR",
0x34 : "MCUSR",
0x33 : "SMCR",
0x30 : "ACSR",
0x2E : "SPDR",
0x2D : "SPSR",
0x2C : "SPCR",
0x29 : "PLLCSR",
0x28 : "OCR0B",
0x27 : "OCR0A",
0x26 : "TCNT0",
0x25 : "TCCR0B",
0x24 : "TCCR0A",
0x23 : "GTCCR",
0x22 : "EEARH",
0x21 : "EEARL",
0x20 : "EEDR",
0x1F : "EECR",
0x1E : "GPIOR0",
0x1D : "EIMSK",
0x1C : "EIFR",
0x1B : "PCIFR",
0x1A : "GPIOR2",
0x19 : "GPIOR1",
0x16 : "TIFR1",
0x15 : "TIFR0",
0x0E : "PORTE",
0x0D : "DDRE",
0x0C : "PINE",
0x0B : "PORTD",
0x0A : "DDRD",
0x09 : "PIND",
0x08 : "PORTC",
0x07 : "DDRC",
0x06 : "PINC",
0x05 : "PORTB",
0x04 : "DDRB",
0x03 : "PINB",
}
}
import io
import os
import re
from subprocess import Popen, PIPE
decode = [
re.compile(r'\b(?P<op>in|lds)\s+\w+,\s+(?P<reg>\w+)'),
re.compile(r'\b(?P<op>out|[cs]bi|sts)\s+(?P<reg>\w+),\s+\w+'),
]
def main(args):
""" Arguments: mcu_name dump_file """
# Find MCU name hence architecture name & registers from first argument
try:
mcu = args[1]
arch = arches[mcu]
cmd = ['avr-objdump', '-m', arch] + args[2:]
reg_dict = regs[arch]
except IndexError:
report("""{0}: Not enough arguments
Syntax: {0} <MCU> <avr-objdump argument list>
Examples:
{0} atmega328 -S main.flash.hex
{0} atmega328 -D -b binary main.flash.bin
""".format(args[0]))
return 1
# Architecture not found or wrong MCU name. Use a blank register list
except KeyError:
reg_dict = []
try:
report("Register dictionary for '{}' not available yet...".format(arch))
except UnboundLocalError:
cmd = ['avr-objdump'] + args[1:]
report("Unknown MCU name: '{}'".format(mcu))
# Architecture & reg dictionary are ready, run disassembler, analyze output
# Examples:
# avr-objdump -D -m avr5 -b binary <file.flash.bin>
# avr-objdump -D -m avr5 <file.flash.hex>
p = Popen(cmd, stdout=PIPE, universal_newlines=True)
try:
# Parse each line from objdump standard output
for line in iter(p.stdout.readline, ''):
matches = decode[0].search(line) or decode[1].search(line)
try:
# If there's a match, replace the special register index (in hex)
# with the matched register name from the register dictionary.
if matches:
# As per the datasheet, registers 0-0x3F are accessed with a
# 0x20 offset only with their memory-mapped version (LDS & STS)
regid = int(matches['reg'], 0)
if matches['op'] in [ 'sts', 'lds' ] and regid < 0x60:
regid -= 0x20
line = ''.join( [
line[:matches.start(0)],
re.sub(matches['reg'], reg_dict[regid], matches[0]),
line[matches.end(0):]
] )
# Instruction matches but operand does not, ignore (maybe no reg list)
except IndexError:
pass
# Don't care if register index is nowhere to be found
except KeyError:
pass
sys.stdout.write(line)
p.stdout.close()
return p.wait()
# We were piped and the pager exited... bail out!
except BrokenPipeError:
return 0
if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
El mejor desensamblador que he visto es IDA. También es compatible con AVR. Pero solo lo he usado para x86. Creo que la característica que está preguntando es una de sus características principales. Puede ser por eso que este desensamblador se llama Interactivo. enlace
Si tiene una cadena de herramientas de código abierto, y esto realmente no está disponible como una opción, me parece que debería ser bastante fácil de proporcionar.
De lo contrario, no debería ser demasiado difícil de hacer en algo que post-procesa la salida. Básicamente, debe expresar una regla para hacer coincidir un patrón en el que una dirección se debe convertir en un nombre de registro, y proporcionar una tabla de búsqueda de direcciones bajas a nombres. Esto podría hacerse de manera ineficiente con un comando sed por registro y formato de instrucciones. realizado en un solo tramo muy complicado de magia por formato, o puede realizarse en casi cualquier lenguaje de programación en el que sepa leer y escribir cadenas en secuencias o archivos.
Uno de los trucos coincidiría con el contexto suficiente para determinar que el número, como 0x3F, es una dirección y no un argumento inmediato.
En un extremo, escribir su propio desensamblador no es necesariamente una empresa tan grande, y puede ser informativo. Puede comenzar haciendo grupos de códigos de operación que usen el mismo formato. Por lo general, la codificación binaria de un determinado estilo de instrucción tiene unos pocos bits para la operación ALU, quizás unos pocos bits de opción, y luego una cantidad de bits que codifican los números de registro del operando.
Lea otras preguntas en las etiquetas avr