我希望能够看到我的 Arduino 草图的汇编语言列表。我怎样才能做到这一点?
更新:我在 Windows 机器上运行 Arduino 软件。
一种方法是在构建创建avr-objdump
的文件上使用。.elf
例如,在 OS XI 上可以这样做:
$ cd ~/arduino-0015/examples/Digital/Blink/applet $ avr-objdump -d Blink.elf
(显然,您在 Windows 上的路径可能不同。)这会产生代码的反汇编,其中一部分看起来像这样:
0000013a <主>: 13a: 0e 94 3e 01 调用 0x27c <init> 13e: 0e 94 97 00 调用 0x12e <设置> 142: 0e 94 80 00 调用 0x100 <循环> 146: fd cf rjmp .-6 ; 0x142 <主+0x8>
如果您使用的是 Linux,您可以按照本教程了解如何在没有 IDE 的情况下为 Arduino 进行编译。
一旦你这样做了,你可以通过运行带有 -s 标志的 gcc 来获得一个程序集列表。
以下(hacky)步骤将在 Windows 上提供 Arduino 草图和相关库的汇编语言列表:
.pde
文件)的目录中-S
到abuild_gcc_opts
变量中abuild.bat
(第 158 行)abuild -r -c <pde_filename>
预计会收到以下警告和错误,您可以忽略它们:
... warning: #warning "This file has been moved to <util/delay.h>."
.\obj\<pde_filename>.cpp.o: file format not recognized: treating as linker script
.\obj\<pde_filename>.cpp.o:1: syntax error
汇编语言列表可以在创建的目录中的.o
文件中找到。obj
例如草图本身的清单在obj\<pde_filename>.cpp.o
-S(不是 s)标志也显示 c 代码。也称为混合列表:
linux: (.arduino/preferences.txt: delete_target_folder=false)
$ cd /tmp/buildxxxx.tmp
$ avr-objdump -dS Blink.cpp.elf
int main(void)
{
init();
2f4: 8a df rcall .-236 ; 0x20a <init>
...
Arduino 编译使用链接时优化 (LTO) 设置,在 C 编译期间创建的汇编文件不包含任何汇编代码 - 只是稍后在 LTO 阶段用于生成实际汇编代码的中间表示。我们想要后者。
碰巧的是,在整个编译过程中最后一次调用汇编程序是从 LTO 阶段获取输出,并将其转换为整个应用程序的目标文件。
要获取此程序集文件,请执行以下操作:
打开%LOCALAPPDATA%\Arduino15\packages\arduino\hardware\avr\1.8.3\platform.local.txt
(如果它不存在则创建它)。添加以下行
compiler.c.elf.extra_flags=-save-temps=obj -fverbose-asm
如果那里已经有这样的行,只需添加上述选项(在右侧=
)。
注意:如果找不到该文件夹,请查找以下文件:boards.txt
、platform.txt
、programmers.txt
。如果您在多个位置找到这些文件,那么您想要的文件应该在您的主目录中(即不在Program Files
or/Applications
或中/usr
),并且应该至少部分与您正在使用的 Arduino 版本相关(如果您安装了多个版本)。
再次构建草图。
查找名为%TEMP%\cc*.ltrans.s
. 每个构建都将创建一个新的此类文件。如果您按时间戳对它们进行排序,则最新的是最新版本。
注意:用符号括起来的环境变量%
在 Windows 对话框中有效。您可以直接将这样的路径粘贴到例如打开或另存为...对话框中,它会起作用。带有 glob ( ) 的路径*
将充当过滤器 (IIRC)。
要知道生成了哪个确切的cc*.s
文件,请将详细选项添加到最终的二进制生成器通道中:
compiler.c.elf.extra_flags=-save-temps=obj -fverbose-asm -v
重新构建,并将 Arduino 中编译状态窗口中的所有输出复制粘贴到例如 Notepad++,然后搜索ar.exe
. 包含的唯一行以此文件ar.exe
的名称结尾:cc
c:/users/[...omitted...]/avr/bin/as.exe -mmcu=avr6 -mno-skip-bug
-o C:\Users\[...]\AppData\Local\Temp\cc3XhU2F.ltrans0.ltrans.o
C:\Users\[...]\AppData\Local\Temp\cc3XhU2F.ltrans0.ltrans.s
文件看起来如何?这是一个简短的摘录,只是为了表明 C 源代码和程序集是混合在一起的——这正是嵌入在.hex
文件中并发送到目标的二进制文件。
.LBE33:
.LBE32:
.LBB34:
.LBB35:
; C:\Users\[...]\Documents\Arduino\sketch_jul01a\sketch_jul01a.ino:29: pinMode(ledPin, OUTPUT);
.file 4 "C:\\Users\\[...]\\Documents\\Arduino\\sketch_jul01a\\sketch_jul01a.ino"
.loc 4 29 0
ldi r22,lo8(1) ; ,
ldi r24,lo8(13) ; ,
call pinMode ;
.LVL55:
; C:\Users\[...]\Documents\Arduino\sketch_jul01a\sketch_jul01a.ino:30: pinMode(relayPin, OUTPUT);
.loc 4 30 0
ldi r22,lo8(1) ; ,
ldi r24,lo8(12) ; ,
call pinMode ;
.LVL56:
; C:\Users\[...]\Documents\Arduino\sketch_jul01a\sketch_jul01a.ino:31: pinMode(ldrPin, INPUT);
.loc 4 31 0
ldi r22,0 ;
ldi r24,lo8(54) ; ,
call pinMode ;
.LVL57:
.LBE35:
.LBE34:
.LBB36:
.LBB37:
这种方法也适用于 Linux 和 MacOS,只是路径略有不同,路径扩展使用不同的语法。关注的两个文件仍然是platform.local.txt
- 您必须创建的文件,因为它最初不存在,以及${TEMP}/cc*.ltrans.s
文件。