GCC能打印出中间结果吗?

检查下面的代码:

#include <avr/io.h> const uint16_t baudrate = 9600; void setupUART( void ) { uint16_t ubrr = ( ( F_CPU / ( 16 * (float) baudrate ) ) - 1 + .5 ); UBRRH = ubrr >> 8; UBRRL = ubrr & 0xff; } int main( void ) { setupUART(); }

这是用于编译代码的命令:

avr-gcc -g -DF_CPU=4000000 -Wall -Os -Werror -Wextra -mmcu=attiny2313 -Wa,-ahlmns=project.lst -c -o project.o project.cpp

ubrr由编译器计算为25,到目前为止这么好。 但是,为了检查编译器的计算结果,我已经查看了反汇编列表。

000000ae <setupUART()>: ae: 12 b8 out UBRRH,r1 ; 0x02 b0: 89 e1 ldi r24,0x19 ; 25 b2: 89 b9 out UBRRL,r24 ; 0x09 b4: 08 95 ret

是否有可能让avr-gcc 在编译时打印出中间结果(或从.o文件中取出信息),所以当我编译代码时,它会打印出一个如(uint16_t) ubbr = 25或类似的行? 这样我可以做一个快速的健全性检查计算和设置。

ATTiny和Linux AVR-GCC中断复位向量在链接器中

GCC有命令行选项来请求它在任何编译阶段后转储出它的中间表示。 “树”转储采用伪C语法,并包含所需的信息。 对于你想要做的事情,在优化管道中有用的点上会发生-fdump-tree-original和-fdump-tree-optimized转储。 我没有一个AVR编译器,所以我修改了你的测试用例,使其能够自我编译,并且可以编译我所拥有的编译器:

typedef unsigned short uint16_t; const int F_CPU = 4000000; const uint16_t baudrate = 9600; extern uint16_t UBRRH,UBRRL; void setupUART(void) { uint16_t ubrr = ((F_CPU / (16 * (float) baudrate)) - 1 + .5); UBRRH = ubrr >> 8; UBRRL = ubrr & 0xff; }

接着

$ gcc -O2 -S -fdump-tree-original -fdump-tree-optimized test.c $ cat test.c.003t.original ;; Function setupUART (null) ;; enabled by -tree-original { uint16_t ubrr = 25; uint16_t ubrr = 25; UBRRH = (uint16_t) ((short unsigned int) ubrr >> 8); UBRRL = ubrr & 255; } $ cat test.c.149t.optimized ;; Function setupUART (setupUART,funcdef_no=0,decl_uid=1728,cgraph_uid=0) setupUART () { <bb 2>: UBRRH = 0; UBRRL = 25; return; }

你可以看到,常量表达式折叠很早就发生了,它已经发生在“原始”转储(这是你可以拥有的最早的可理解的转储),并且优化进一步将转换和掩码操作折叠成了写入UBRRH和UBRRL。

文件名(003t和149t)中的数字可能会有所不同。 如果要查看所有 “树”转储,请使用-fdump-tree-all 。 还有“RTL”转储,看起来不像C,可能对你没用。 如果你很好奇,但是, -fdump-rtl-all将会打开它们。 总共有大约100个树和60个RTL转储,因此在暂存目录中执行此操作是一个好主意。

(Psssst:每当你在括号里面放上空格时,上帝就会杀死一只小猫。)

打印中间结果可能有一个解决方案,但需要一些时间才能实施。 所以只有一个相当大的源代码库是值得的。

你可以定制你的GCC编译器; 通过一个插件(痛苦地用C或C ++编码)或者通过MELT扩展。 MELT是一个高级的,Lisp式的,特定于领域的语言来扩展GCC。 (它被实现为GCC的[meta]插件并被转换为适合GCC的C ++代码)。

然而,这种方法要求您了解GCC内部,然后添加您自己的“优化”通行证来执行面向方面的编程 (例如使用MELT)来打印相关的中间结果。

你也可以看看生成的程序集(也可以使用-fverbose-asm -S作为GCC的选项),也可以在生成的-fdump-tree-gimple表示中(可能使用-fdump-tree-gimple )。 对于某些交互式工具,请考虑图形化的MELT探针 。

也许增加你自己的内建(使用MELT扩展)像__builtin_display_compile_time_constant可能是相关的。

我怀疑有一个简单的方法来确定编译器的功能。 gcc中可能会有一些工具专门用于转储语言的中间形式,但绝对不容易阅读,除非您真的怀疑编译器做错了什么(并且有一个非常小的例子来显示它) ,不太可能将它用于任何有意义的事情 – 仅仅是因为太多的工作来跟踪正在发生的事情。

一个更好的方法是添加临时变量(也许是打印)到你的代码,如果你担心它是正确的:

uint16_t ubrr = ( ( F_CPU / ( 16 * (float) baudrate ) ) - 1 + .5 ); uint8_t ubrr_high = ubrr >> 8 uint8_t ubrr_low = ubrr & 0xff; UBRRH = ubrr_high; UBRRL = ubrr_low;

现在,如果你有一个非优化的构建,并在GDB中逐步完成,你应该能够看到它的功能。 否则,在代码中添加某种打印输出以显示值…

如果你不能在目标系统上打印它,因为你正在设置将用于打印的uart,然后在本地主机系统上复制代码并在那里进行调试。 除非编译器非常麻烦,否则应该从相同的编译中获得相同的值。

这里有一个黑客:现在只需要手动自动化你正在做的事情。

在你的makefile中,确保avr-gcc产生一个反汇编( -ahlms= output.lst )。 或者,使用自己的反汇编方法作为makefile中的后编译步骤。

作为后编译步骤,使用您最喜欢的脚本语言处理您的列表文件,以查找out UBRRL和out UBRRL行。 这些将从寄存器中加载,所以你的脚本可以将之前的分配分配到将被加载到UBRRH和UBRRL寄存器中。 然后,脚本可以从加载到通用寄存器的值中重新组合UBRR值,通用寄存器用于设置UBRRH和UBRRL 。

这听起来比Basile Starynkevich对MELT扩展的非常有用的建议更容易。 现在,如果认为这个解决方案看起来很脆弱,我们首先应该考虑这个问题:

我们知道 (至少在你的处理器上) out UBRR_,r__会出现在反汇编列表中:除此之外,没有其他方法可以设置寄存器/写数据到端口。 有一件事情可能会改变,就是这些行之间的间隔,但这可以通过脚本轻松处理

我们也知道,只能从通用寄存器中out指令,所以我们知道通用寄存器是指令行的第二个参数,所以不应该是一个问题。

最后,我们也知道这个寄存器将在out指令之前被设置。 这里我们必须考虑到一些可变性:而不是LDI (立即加载),avr-gcc可能会产生一些其他指令来设置寄存器值。 我认为作为第一次通过,脚本应该能够解析立即加载,否则转储它发现涉及将被写入UBRR_端口的寄存器的最后指令。

如果你改变了平台,脚本可能不得不改变(一些处理器有UBRRH1 / 2寄存器UBRRH ,但是在这种情况下,你的波特代码将不得不改变,如果脚本指出它不能解析反汇编,至少知道你的支票没有被执行。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Git安装和使用 Git安装和使用 刚开始用git的小白适用,,转自http://www.cnblogs.com/qijunjun/p/7137207.html 实际项目开发中,我们经常会用一些版本控制器来托管自己的代码,今天就来总结下Git的相关用法,废话不多说,直接开写。 目的:通过Git管理g
fatal: remote origin already exists.解决方法 第一个问题git remote add origin**************fatal: remote origin already exists.(报错远程起源已经存在。)上网查了下,有很多小白遇到过这个问题,以
git常用命令(二)查看历史记录 git log [--pretty=oneline] [ --oneline] / reflog Eniac-W 于 2020-10-18 18:12:38 发布 2368 收藏 3分类专栏: git 文章标签: git版权 git专栏收录该内容10 篇文章0 订阅
git之如何把本地文件上传到远程仓库的指定位置 git专栏收录该内容2 篇文章0 订阅订阅专栏2018.11.26添加内容: 对于自己的仓库,我们建议将远程仓库通过clone命令把整个仓库克隆到本地的某一路径下。这样的话我们从本地向远程仓库提交代码时,就可以直接把需要提交的文件拖到我们之前克隆下来的
代码规范之 lint-staged 在代码提交之前,进行代码规则检查能够确保进入git库的代码都是符合代码规则的。但是整个项目上运行lint速度会很慢,lint-staged能够让lint只检测暂存区的文件,所以速度很快。 安装与配置 安装husky和lint-staged: yarn add hu
方法:1、文件没有git操作时用“git checkout--文件”命令还原;2、文件提交到暂存区时用“git reset HEAD”命令回退当前版本还原;3、文件提交到仓库区时用“git reset HEAD^”命令回退上一个版本还原。 本文操作环境:Windows10系统、Git2.30.0版、
使用Git将本地文件提交到远程仓库 一 操作准备条件: git远程仓库已经建好了,本地文件已经存在了,现在要将本地代码推到git远程仓库保存。 解决办法如下: 1、(先进入项目文件夹)通过命令 git init 把这个目录变成git可以管理的仓库 git init 2、把文件添加到版本库中,使用命令
GitHub克隆代码到本地全教程 因为工作原因更换电脑,想要从GitHub上拉取代码的话需要重新配置ssh keys,时间过的久了怕忘记就把步骤给记录下来。 具体步骤: 1.安装git 这我就不说了 2.在TortoiseGit的安装文件中找到 puttygen.exe应用程序 ,默认应该都是 :C
github上传项目的时候报出git@github.com: Permission denied (publickey). fatal: Could not read from remote repo 前言 会不会有程序员小伙伴在刚开始使用github的时候上传项目的时候困难重重,但是又基于自己本身
查看历史 git log --pretty=onelinegit log (然后一直按enter键) 一个是切换根据历史里面的id切换git checkout ID git log 需要不断按enter键出来历史提交记录 git log --pretty=oneline 是直接出来历史记录
Git工作原理及常用命令 欧怼怼发布于&#160;2020-12-08 git介绍 git(读音/ɡɪt/)是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。git是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。 git
git git提交项目的具体流程 git项目流程:以下主要有3个角色:负责人、成员A、成员B(若负责人也要修改代码,则负责人同时兼任2个角色:负责人、成员) 主要负责人:搭建项目架构且提交到git上1.github官网登录后,新建仓库,生成地址url,复制线上仓库.git结尾的地址url2.在一个空
git上传项目全部流程 一、下载git 进入网址:https://git-scm.com/downloads; 点击中的Download 2.16.0 for Windows; 在中选择蓝色字段点击,根据电脑64或32位选择适合的下载,点击即可进行下载,下载完成后傻瓜式安装,一直点击下一步即可完成安
Your local changes to the following files would be overwritten by checkout问题的解决 于 2018-07-17 11:38:27 发布 Git 的本地版本管理有三个部分 名称&#x9;说明工作区(Working Directory)&#x9;
Git配置SSH Keys步骤使用教程 1.若是首次安装使用git,先配置用户名称和邮箱(如果有就不需要配置) 打开Git Bash,输入 git config --global user.name &quot;姓名&quot;git config --global user.email &quot
基本配置完成,接下来就是上传你要上传的项目了。 1、初始化git 进入你要上传的项目的文件夹,在文件夹内鼠标右击,选择“Git Bash Here”打开git命令行,输入: $ git init 目的是初始化git,并且会创建个“.git”文件夹,里面有个“config”就是用来保存远程厂库路径地址
本篇内容主要讲解“gitee如何上传代码”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“gitee如何上传代码”吧! ...
这篇“从gitee上下的代码如何用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这...
这篇文章主要介绍“gitee如何下载仓库里的项目”,在日常操作中,相信很多人在gitee如何下载仓库里的项目问题上存在疑惑,小编查阅了各式资料,整理出简单好用的...
本篇内容主要讲解“怎么在Gitee上更新代码”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么在Gitee上更新代...