8 GP sw集装箱gp是什么意思思

您的可投注余额不足, 请充值!
(点"充值"跳到充值页面,点"返回"可进行修改)
您本次购买份数为1份,总金额为2.00元,请确认!
方案提交成功,请注意查看出票状态!
您还可以选择:&&|&&
下载手机彩票客户端,中奖第一时间通知您!
双色球专题
您现在的位置:&中国福利彩票双色球专题
每周二、四、日晚21:30开奖,单注最高奖金1000万元
中国福利彩票双色球预测
[媒体看点]
[媒体看点]
[媒体看点]
[媒体看点]
[媒体看点]
[媒体看点]
[媒体看点]
[媒体看点]
[媒体看点]
[媒体看点]
中国福利彩票双色球专家推荐
[栋栋团队]
[许氏先锋]
[神采飞扬]
[小吴姐姐]
[馒头1225]
[商业屠夫]
[洞庭湖水]
版权所有&&股票代码:WBAI&&客服热线:&&&&&&&&&&郑重提示:彩票有风险,投注需谨慎&&不向未满18周岁的青少年出售彩票&&|&&&&|&&|&&
全新原装进口现货热卖,品牌代理&
电话:4/832446
地址:深圳市福田区华强北路赛格科技园4栋中7L09室(
原厂最新批次&
一级代理&全新进口&原装&现货&特&
电话:3/230423
地址:广东省深圳福田区振兴路华匀大厦1栋799
全新原装现货&长期供应!&
电话:755-
地址:福田区华强北路华联发综合楼828
一级代理&全新原装&现货特价!&
电话:1/0755-2
地址:深圳市福田区振兴路西101号华匀大厦1栋7楼709
2016最新批次&
一级代理&全新原装&现货特价!国&
地址:深圳市福田区航天路与振兴路交汇华匀大厦7楼7
原装现货&专业提供&
电话:8-8090
地址:广东省深圳市福田区中航路鼎诚国际大厦1017室
电话:0/827859
地址:深圳市华强北深圳市福田振华路113号新欣大厦B
100%原装现货可出样品&
电话:0-234874
地址:福田区振兴路华匀大厦3F&&福田区中航路高科德
只做原装公司现货100%真实代理产&
电话:755-6010
地址:深圳市福田区振兴路101号华匀大厦517房间
10+原装ROHS&
全新原装进口环保现货特价&
电话:&#81290★
地址:中国深圳市福田区华强北路现代之窗大厦B座32H
100%进口原装假一罚百!可开17%增&
电话:49/83204
地址:深圳市福田区华强北上步工业区102栋608
原装现货!品质为先!请来电垂询!&
电话:021-9666
地址:上海市嘉定区虞姬墩路505号601(杨柳经济城对
假一罚百!公司原装现货&绝无虚假&
电话:4/892020
地址:深圳市福田区华强北海外装饰大厦A座6F08室/门
【最新年份】&
全新原装100%保证质量,绝对自家货&
电话:755-&//&8321
地址:深圳市福田区华强北上步工业区101栋6楼西610室
电话:2可开17%
地址:深圳市新亚洲二期二楼N2A013柜,深圳市华强北路
只做进口原装,现货库存,欢迎来&
电话:021--
地址:上海市徐汇区中山南二路1007号&(中煌大厦)1
原装现货(1号库)&
地址:福田区中航路国利大厦1539室
全新原装正品,现货优势库存&
电话:7/837777
地址:美驻深办公室:广东省深圳市福田区上步工业区2
全新原装正品,现货优势库存&
电话:8/837776
地址:美驻深办公室:深圳市福田区华强北上步工业区2
进口原装特价热卖中,可开17%票!&
地址:深圳福田区雷圳大厦2208
主营全系列进口原装产品,现货&
电话:2/825160
地址:广东省深圳市福田区上步工业区201栋530室
中国唯一指定代理商√√√&特价!&
电话:4/0755-8
地址:福田区振华路华乐楼615室
电话:3/832538
地址:深圳市福田区华强北街道华强北路上步工业区10
原装现货!100%真实库存!&
电话:2/229207
地址:深圳市福田区华强北路上步工业区501栋412室
全新&&&原装现货&&&特价!!!&
电话:1/230631
地址:深圳市福田区振兴路西101号华匀大厦1栋7楼709
进口原装假一赔十&
电话:755-2930
地址:深圳市福田区华强北赛格科技园2栋中809室.
原装现货&随时看货&
电话:8-6017
地址:广东省深圳市福田区华强北振中路鼎诚国际大厦
★★★郑重承诺只做原装进口大量&
电话:755-
地址:深圳市福田区工发路上步工业区201栋东座519室
全新原装,欢迎订购!
&
电话:021-7256
地址:上海市黄浦区北京东路668号科技京城西楼
全新原装现货&长期供应!&
电话:755-
地址:福田区华强北路华联发综合楼828
地址:深圳市福田区福田上步101
√ 欧美I品 &
【】实时报价有图&PDF&
&
电话:010-/34/3
地址:北京市海淀区增光路27号院增光佳苑2号楼1单元
全新原装现货特价&
电话:9&&83376
地址:广东省深圳市深圳南山区科技园产学研楼706
ANALOGDEV&
全新库存供应&
地址:深圳市福田区华强北路华强广场D座20&i室
ROHS◆◆进口原装现货◆◆&
◆★价格最低,只做原装正品货◆&
地址:广东省深圳市福田区华富路1046号华康大夏2栋5
原装进口现货,假一赔十!&
地址:深圳市福田区振华路中航苑鼎城大夏1607室
原装现货&专业提供&
电话:8-8090
地址:广东省深圳市福田区中航路鼎诚国际大厦1017室
原装现货&专业提供&
电话:8-8090
地址:广东省深圳市福田区中航路鼎诚国际大厦1017室
原装现货&专业提供&
电话:8-8090
地址:广东省深圳市福田区中航路鼎诚国际大厦1017室
16 ld PDIP&
低价支持实单,样品可拆&
电话:3/369373
地址:深圳市福田区振兴路101号华匀大厦1栋2楼204室
原装正品!价格优势!
&
地址:广东省深圳市华强北中航路
全新原装现货&
电话:021-1825
地址:上海市闸北区海宁路1399号金城大厦1513室
电话:1/832491
地址:深圳市福田区红荔路群星广场A座2816室
全新原装,欢迎订购!
&
电话:021-7256
地址:上海市黄浦区北京东路668号科技京城西楼
100全新原装★★特价供应★★特价&
地址:中航路佳和电子市场2A012
原装现货特价大量供应&
地址:广东省深圳市福田区振兴西路华康大厦2栋
一级代理.原装特价现货!&
电话:2/832256
地址:深圳市福田区上步工业区201栋530室
12+ ★100%原装正品现货库存优势供应★&
★100%公司全新进口原装现货库存&
地址:深圳市福田区振兴西路109号华康大厦2栋607室
全新原装现货&市场最低价!&
电话:2480
地址:深圳市福田区中航路都会电子城市场2B028
最专业的集成电路供应商,公司承&
电话:0(亚洲地
地址:深圳市福田区华强北路赛格广场35楼3501B室。亚
服务热线 深圳:9  传真:2
库存上载: 客服QQ:& 戴表不走冤枉路 四种男士类型的不同选择
戴表不走冤枉路 四种男士类型的不同选择
来源:腕表之家
类型:原创
作者:李帅
& & [&钟文化]现代社会,什么样的男人最吸引女人的目光?男士们心中有一个努力的方向或者衡量的标准吗?有人说,四十岁的男人最有魅力。因为四十岁的男人精力旺盛,事业有成,经济可靠,家庭稳定,而且特别懂得女人的心理。我却对此不以为然,每个阶段的男人都有专属的特点,都会获得不同女士的欣赏目光,不能用一个阶段的目光来相互比较。从大致来分,男人可以分为以下四类时尚潮男、翩翩绅士、贴心暖男、屌丝男士(此种分类仅供参考和娱乐,并不作为唯一标准)。不同类型的男人对的需求也是不同的,下面编辑就为每种男人推荐几款适合的腕表,各位男士们请对号入座吧。
& & 时尚潮男
& & 66F-1140-52B
& & 谈到时尚这个词语,在年轻人的世界里似乎从不陌生,因为追求时尚早已蔚然成风。所谓潮男,不见得是小说中所写的“有光洁白皙的脸庞,乌黑深邃的眼眸,泛着迷人的色泽……”不可否认有花样的美男子,同时也有一部分虽拥有普通长相却能Hold住潮牌的男神们,嘴角上扬露出酷酷的坏笑,令不少年轻的mm也心醉啊!在穿衣搭配上,时尚潮男不会放过任何一个装扮自己的机会,尤其是对于腕表,这样的腕上尤物、装备利器,绝对的列在装备指南的优先位置。
& & 最近由于召开APEC会议,会上的各种细节都成了大众的观众点,APEC蓝也被大家热议不断。想必时尚的男士们也都蠢蠢欲动,不仅渴望蓝色的礼服,也想拥有一款蓝色腕表了吧。“”系列是表当中最为坚固耐用的腕表,外观设计亦是多元丰富,延续09年的Ocean&Blue深海意念。全日历盈亏飞返计时秒表-52B,搭配45毫米直径的,蓝色单向旋转外圈及蓝色基调的面盘,勾勒出非凡杰作,像海洋一样深邃而澄澈。运动气息浓厚,3点钟及9点钟位置配备30分、12时计时小盘,小秒显示则位于6点钟位置,一轮人脸月相居于其上,趣意盎然。除了具备月相全历显示功能,还兼具飞返计时功能,只要单个按钮,即可瞬间停止计时、归零,并重新启动计时。
& & 内在却更加进化,“五十噚”家族中新加入的生力军,其搭载的66BF8自动上炼机芯,将导柱轮飞返计时和月相盈亏完美结合,打造运动腕表的典雅风情。以往表厂所推出的全日历月相机制均无法调整指针显示,避免伤害日历机制的精密组件;而本次发表的月相盈亏全日历机制,则来自F185机芯,突破性的革命技术,让玩家无需担心即可轻松调校日历显示,而不需担心损坏机芯。
& & &Big&Bang&Unico碳纤维
& & 时尚象征着活力、热情、不拘一格,与宇舶Big&Bang所呈现的设计理念不谋而合,整款腕表的构思和设计将的DNA:运动、性能、高科技表达的淋漓尽致。所有设计以时尚、实用和理性为原则,无需任何多余配件的装饰。
& & &Big&Bang&Unico系列拥有更为傲人的45.5毫米直径表壳,彰显时尚机械外观;表圈为宇舶表标志性的6颗H型螺钉,设计新潮、巧妙且更凸显技术(每颗螺钉顶部浮凸设计,更加鲜明,可以选择抛光或者亚光的修饰效果)。表盘的独特设计将机械的复杂感呈现地淋漓尽致,红色的时间显示刻度尤为突出个性,两个计时小表盘由抛光的圆环环绕,其中分钟计时表盘位于3点钟位置,小秒针表盘位于9点钟位置,日历窗格显示同样位于3点钟位置。指针经过了重新修饰加工,两段式刻面覆黑色夜光涂层。另外值得一提的是,新的表冠设计:全新旋入式表冠——由压制成型的天然橡胶包裹,末端饰以源自螺钉形状的经典的H标识,从任何一个角度都能感受到这款表硬朗的机械感。
& & 不仅外观具有硬朗的男士风度,从舒适度和功能性着眼,这款腕表也能满足时尚控的要求。UNICO机芯作为宇舶表最具标志性意义的自产计时机芯,自然成为Big&Bang&Unico系列的核“芯”所在。UNICO机芯完全由宇舶表的微观机械师、工程师和制表师独立设计、研发、制造并组装。这款飞返计时机芯(可以在任何时间进行重置),在制表业中独树一帜,搭配双按钮结构和日期显示。其独特之处在于机芯在表盘一侧整合了带双水平离合的独特定位机构和著名的“导柱轮”,清晰可见。
& & 翩翩绅士
& & 冬天是最能展现绅士风貌的一个季节,有风度的大衣、有型的西装、得体的领带,再加上一双得体的皮鞋,让人眼前一亮,体现彬彬有礼的绅士风格。此时,如果在腕间在增添一份腕表的装饰,绝对是无懈可击。而且对于已经到了绅士阶段的男士,他们更需要的便是那种浮躁过后的成熟与稳重,不见得是“国民大叔”吴秀波那种类型,但最起码也要有类似的几分情调与品位。
& & &1&系列109.032&18K
& & &1&具备诸多特质,如偏心表盘、大日历显示、三天动力储存,以及尽显无暇工艺的表厂自制机芯。自18&年前首度面世,此表便为精密制表业带来新气象,并从此成为了的标志。朗格LANGE&1&月相腕表系列109.032&18K玫瑰金腕表将完美展示德式制表风格,月相盈亏显示就如真的月亮一样,精确地仿效月亮的运行轨迹。
& & 在银白色的表盘上,腕表被分成了几个不同的部分,右侧的偏心小时占据了38.5毫米表盘的半壁江山,突出读时的准确性。六点钟方向的小秒盘还可以昼夜显示,蓝色的半圈代表夜晚,深邃的夜空中点缀着弯弯的月亮和几颗星星,给人一种宁静之美,整体布局非常匀称和谐。
& & 从功能角度来讲,右侧九点钟位置的逆跳很自然地讲上方的大日历显示窗口和月相分开,不同大小的窗口和分区使得这款表的表盘赋有美观,又不显得凌乱。月相和小秒盘放在了一起,充分的空间显示出了最多的功能。十二点钟方向还拥有朗格的标志,以圆弧型的方式呈现在表盘上,以整体的设计统一和谐。朗格的指针也采用重金属材质,显得高贵而奢华,对于守时的绅士,这款腕表在任何场合都会为您添一份风度与品位。
& & &1945系列-BB6A腕表
& & GP芝柏全新玫瑰金Vintage&1945日历表的长方形外观是直线和弧线和谐组合的结晶:精美的造工、贴手的弧度线条和跟表冠灵神合一的两侧凸面,以三个层次展现含蓄的线条比例美感。弧线和直角的对比延伸至微拱表盘和抛光数字时标中,突显上述细节的立体感;方形的表壳独具特色,表盘中央有精美机刻扭索花纹并装配王太子指针,饰以一圈闪烁优雅的阿拉伯数字,小秒针和日历分别置于9时和1时半位置,布局均衡有致,完美演绎该系列的简洁清丽、线条比例恰到好处的高贵气质。
& & 搭载芝柏全新GP&3300自动上链机械机芯的腕表,运用超凡的工艺把复杂的机芯完美地融合在纤巧的表壳之内,一定要运用最纯熟的技术才能成功。而这枚修饰精美的机芯可以从蓝宝石水晶表背一览无遗,腕表搭载的GP3300机芯一直以稳定可靠的特质而闻名,采用高精度微调摆轮游丝系统,是品牌中常用的基础机芯。其装饰也遵循了制表传统:由日内瓦波纹、珍珠圆点打磨纹和蓝钢螺钉组成。
& & 贴心暖男
“暖男”这个称呼,你最先想到的是体贴细心的张亮,还是好男人的黄磊呢?不错,顾名思义,暖男就是指那些顾家、爱家,懂得照顾老婆,爱护家人,能给家人和朋友温暖的阳光男人。
& & 大明火珐琅日历大秒针腕表
& & 雅克德罗的风格在我心中一直以“优雅”二字著名,搭配暖男在合适不过了。这款腕表分别有红金或白金的39毫米和43毫米两种表盘,可谓美学上的一大飞跃。采用雅克德罗独有传统工艺大明火珐琅制成的双层珐琅表盘,带来更为深邃、立体的时计阅读体验,而两个小表盘所组成的品牌幸运数字“8”显得尤为完美、明晰。
& & 雅克德罗擅长机芯润饰,此款机芯也不例外:主板双面珍珠圆纹研磨;齿轮采用倒角、抛光、圆纹效果;精钢部分则采用柔和倒角、直线纹路;边角部分经手工打磨抛光,所有这些工艺都赋予机芯精美、独特的外观,透过透明底盖,机械之美尽收眼帘。为配合象牙色大明火珐琅日期显示大秒针的隆重发布,机芯表面还特别饰以扇形日内瓦波纹,彰显其尊贵的身份。
& & “屌丝”男士
& & 现在“屌丝”这个词语也被用的相当泛滥了,随随便便一个人都自称为屌丝。其实最初的“屌丝”不是有志青年,更不是精英,从年龄上看,“屌丝”多是上80后或者90后的刚踏入社会的年轻人或是在校学生,随着网络的传播,越来越多人喜欢用屌丝来形容自己。
& & 颜色的搭配是我挑选此款腕表的首要原因,白天,你是优雅简洁的黑色智者,沉稳睿智,无处不展现专业与执着;夜幕降临,你变身激情四射的橙色精灵,释放跳动的活力与灵动的天资,演绎独具风采的男人身情怀。男士-B腕表独具匠心地配备了橙色与黑色小牛皮真皮轧鳄鱼皮花纹可更换表带,便利的滑扣设计只需轻巧一拨即可装配,为佩戴者带来充满互动的体验,代表一直秉承的人性化设计。
& & 这款腕表搭载机械机芯、316L不锈钢经黑色PVD处理表壳、螺旋表冠及后盖、处处彰显品质;42mm表盘,代表你的恣意大气;双面防眩目防刮蓝宝石镜面包裹着表盘上黑色纵向日内瓦波纹、经橙色Super-LumiNova(R)夜光处理的刻度,是你个性的体现。
& & 300&M&Quartz&系列腕表
& & 这一款腕表是表带,采用蓝宝石水晶玻璃表镜,蓝色的表盘配有荧光显示刻度,优雅大气的风格不言而喻。41毫米的壳非常适合男士的手腕,银色的表链经过细致的打磨,彰显品牌的用心之处。具有基本的时间和日期显示功能,最后防水深度300米,足以满足佩戴者的日常娱乐活动。
总结:年轻的男人渴望凸显自己的个性,在每个场合都想崭露头角,而成熟的男人即使不发表言论,都会令人感到强大的气场。一个男士的品位是在举手投足以及行事风格中凸显的,腕表作为男人为数不多的装饰和实用品,着实需要好好搭配才是。以上四种男士风格腕表,仅代表一种方案而已,如果您需要更多品牌的腕表介绍,可以关注腕表之家的其他相关报道,也可以体验腕表之家的资讯服务功能。(图/文&腕表之家&李帅)
文章中涉及到的4款产品
价格:¥191000(厂商指导公价)
,45毫米,
材质:精钢
价格:¥191000(厂商指导公价)
,45毫米,
材质:精钢
,41毫米,
材质:精钢
价格:¥210000(厂商指导公价)
,36x35.25毫米,
材质:18k玫瑰金
价格:¥316000(厂商指导公价)
,38.5毫米,
材质:18k玫瑰金
我来写评论
最新腕表点评基础知识介绍:
MIPS32的内部寄存器。
最简单的办法就是通过GDB的命令,可以获得下面的列表
(gdb) info registers
&&&&&&&&& zero&&&&&& at&&&&&& v0&&&&&& v1&&&&&& a0&&&&&& a1&&&&&& a2&&&&&& a3
&R0&& 0f 0e
&&&&&&&&&&& t0&&&&&& t1&&&&&& t2&&&&&& t3&&&&&& t4&&&&&& t5 &&&&&&t6&&&&&& t7
&R8&& 03 803cb0 00008
&&&&&&&&&&& s0&&&&&& s1&&&&&& s2&&&&&& s3&&&&&& s4&&&&&& s5&&&&&& s6&&&&&& s7
&R16& 03bb0 00 00
& &&&&&&&&&&t8&&&&&& t9&&&&&& k0&&&&&& k1&&&&&& gp&&&&&& sp&&&&&& s8&&&&&& ra
&R24& 000 0bbd0 807fffb8 00830
&&&&&&&&&&& sr&&&&&& lo&&&&&& hi&&&&& bad&&& cause&&&&&& pc
&&&&& 07 30
&&&&&&&&&& fsr&&&&& fir
&&&&& 00000
除了32个通用寄存器以及别名外,还有8个专用寄存器,分别是:
sr ( 全称Status ,CP0 Reg12) Processo and shadow set control
lo ( 全称WatchLo , CP0 Reg18) Low-order watchpoint address
hi ( 全称WatchHi, CP0 Reg19) High-order watchpoint address
bad ( 全称BadVAddr, CP0 Reg8) Reports the address for the most recent address-related exception
cause (CP0 Reg13) Cause of last exception
pc 很明显这个是程序计数寄存器,奇怪的是在32个通用寄存器以及CP0的32个寄存器中都没有找到他,最接近的一个是CP0Reg14 EPC (Program counter at last exception.)
fsr 浮点相关寄存器,具体用途不明
fir浮点相关寄存器,具体用途不明
下表描述32个通用寄存器的别名和用途
常量0(constant value 0)
保留给汇编器(Reserved for assembler)
函数调用返回值(values for results and expression evaluation)
函数调用参数(arguments)
暂时的(或随便用的)
保存的(或如果用,需要SAVE/RESTORE的)(saved)
暂时的(或随便用的)
全局指针(Global Pointer)
堆栈指针(Stack Pointer)
帧指针(Frame Pointer)
返回地址(return address)
Table: MIPS registers and the convention governing their use.
Register Name
Constant 0
Reserved for assembler
Expression evaluation and results of a function
Expression evaluation and results of a function
Argument 1
Argument 2
Argument 3
Argument 4
Temporary (not preserved across call)
Temporary (not preserved across call)
Temporary (not preserved across call)
Temporary (not preserved across call)
Temporary (not preserved across call)
Temporary (not preserved across call)
Temporary (not preserved across call)
Temporary (not preserved across call)
Saved temporary (preserved across call)
Saved temporary (preserved across call)
Saved temporary (preserved across call)
Saved temporary (preserved across call)
Saved temporary (preserved across call)
Saved temporary (preserved across call)
Saved temporary (preserved across call)
Saved temporary (preserved across call)
Temporary (not preserved across call)
Temporary (not preserved across call)
Reserved for OS kernel
Reserved for OS kernel
Pointer to global area
Stack pointer
Frame pointer
Return address (used by function call)
2.&&&&& 基于Linux的环境,应用程序可以通过抛出信号的方法挂起当前的任务,操作系统会将该任务控制块信息(TCB)交由应用程序注册的信号处理函数来处理,该信息中包含了
下面这个信号量上下文结构体,里面含有我们需要的CPU寄存器信息。
linux/2.4.20/include/asm-mips/sigcontext.h
&* Keep this struct definition in sync with the sigcontext fragment
&* in arch/mips/tools/offset.c
struct sigcontext {
&&&&&&& unsigned int&&&&&& sc_&&&&&&&&& /* Unused */
&&&&&&& unsigned int&&&&&& sc_
&&&&&&& unsigned long long sc_
&&&&&&& unsigned long long sc_regs[32];
&&&&&&& unsigned long long sc_fpregs[32];
&&&&&&& unsigned int&&&&&& sc_&&&&&&&&& /* Unused */
&&&&&&& unsigned int&&&&&& sc_fpc_
&&&&&&& unsigned int&&&&&& sc_fpc_&&&&&&&&& /* Unused */
&&&&&&& unsigned int&&&&&& sc_used_
&&&&&&& unsigned int&&&&&& sc_&&&&&&&&& /* Unused */
&&&&&&& unsigned long long sc_
&&&&&&& unsigned long long sc_
&&&&&&& unsigned int&&&&&& sc_&&&&&&&&&&& /* Unused */
&&&&&&& unsigned int&&&&&& sc_&&&&&&&& /* Unused */
&&&&&&& unsigned long&&&&& sc_sigset[4];&&&&&&& /* kernel's sigset_t */
mips32常用汇编指令描述
#include &stdio.h&
#include &stdlib.h&
int func_b(int a)
&&& return 0;
int func_a(int a)
&&& func_b(0);
&&& return 0;
int main(int argc, char* argv[])
&&& int temp = 0;
&&& func_a(temp);
&&& return 0;
下面是将-O2编译出的elf反编译后func_a的汇编指令:
-&& 0x &func_a&:&&&& &&& lui a0,0x8000& /* a0 = 0x */
-&& 0x &func_a+4&:&&&&&& lui a1,0x8000 /* a1 = 0x */
-&& 0x &func_a+8&:&&&&&& addiu& sp,sp,-24
/* sp = sp - 24 = 0x807fffd0 - 24 = 0x807FFFB8 */
-&& 0x8000081c &func_a+12&:&&&&& addiu& a0,a0,12876
/* a0 = a0 + 12876 = 0x8000324C */
-&& 0x &func_a+16&:&&&&& addiu& a1,a1,12888
/* a1 = a1 + 12888 */
-&& 0x &func_a+20&:&&&&& sw& ra,16(sp)
/* SW Store Word Mem[Rs+offset] = Rt
sp = 0x807FFFB8
功能相当于下面的C代码
*(unsigned int*)(sp + 16) = ra */
-&& 0x &func_a+24&:&&&&& jal 0x80000dd0 &printf&
/* JAL Jump and Link GPR[31] = PC + 8
PC = PC[31:28] || offset&&2
ra = pc+8 = 0x + 8 = 0x
pc = 0x80000dd0 */
&&& 0x8000082c &func_a+28&:&&&&& li& a2,78
-&& 0x &func_a+32&:&&&&& jal 0x &func_b&
&&& 0x &func_a+36&:&&&&& move&& a0,zero
-&& 0x &func_a+40&:&&&&& lw& ra,16(sp)
-&& 0x8000083c &func_a+44&:&&&&& move&& v0,zero
/* v0 = 0 */
-&& 0x &func_a+48&:&&&&& jr& ra
JR Jump Register PC = Rs
&&& 0x &func_a+52&:&&&&& addiu& sp,sp,24
阅读上面代码发现一个问题:
为什么ra = pc+8而不是pc+4呢?这样看来0x8000082c、0xx个地址对应的指令不会被执行到。
下面这段来自《MIPS32 4K Processor Core Family Software User&s Manual》
Jump and branch instructions change the control flow of a program. All jump and branch instructions occur with a delay of one instruction: that is, the instruction immediately following the jump or branch (this is known as the instruction in the delay slot) always executes while the target instruction is being fetched from storage.
简单的说,因为MIPS的多级流水机制导致Jump和Branch指令后面的一个指令会被放在延时槽中,无条件执行。
下面是一些网站上找到的描述:
How to traceback call stack on MIPS arch?
Gcc saves the frame pointer to fp(s8) register at the beginning of each function if compiling source with -O0. But& it won't do so if compiling source with -O2. Without frame pointers, can I trace back call stacks in current function context? Or is there any option which forces gcc to save frame pointers for MIPS arch?
这个问题是关于GCC优化的,看看下面这个表就清楚了。从实际测试情况看,fp(s8)也就是通用寄存器30可以用sp也就是通用寄存器29来代替,因为在函数领空(不包含子函数调用)的时候sp是保持固定值的,因为没有类似于x86的pop和push指令,该问题只着眼于当前函数上下文,没有考虑到向前追溯的问题。
mips_fp_be-gcc -O0 -g test.c -o btO0
mips_fp_be-objdump -S btO0 & asmO0.txt
mips_fp_be-gcc -O2 -g test.c -o btO2
mips_fp_be-objdump -S btO2 & asmO2.txt
00400e0c &main&:
main (int argc, char **argv)
& 400e0c: 3c1c0fc0 lui& gp,0xfc0
& 400e10: 279c79b4 addiu&&& gp,gp,31156
addu gp,gp,t9
& 400e18: 27bdffd8 addiu&&& sp,sp,-40
& 400e1c: afbc0010 sw&& gp,16(sp)
& 400e20: afbf0020 sw&& ra,32(sp)
& 400e24: afbe001c sw&& s8,28(sp)
& 400e28: afbc0018 sw&& gp,24(sp)
& 400e2c: 03a0f021 move s8,sp
& 400e30: afc40028 sw&& a0,40(s8)
& 400e34: afc5002c sw&& a1,44(s8)
& print_backtrace ();&
& 400e38: 8f9980a4 lw&& t9,-32604(gp)
& 400e48: 8fdc0010 lw&& gp,16(s8)
& return 0;
move v0,zero
& 400e50: 03c0e821 move sp,s8
& 400e54: 8fbf0020 lw&& ra,32(sp)
& 400e58: 8fbe001c lw&& s8,28(sp)
& 400e5c: 03e00008 jr&& ra
& 400e60: 27bd0028 addiu&&& sp,sp,40
00400de4 &main&:
main (int argc, char **argv)
& 400de4: 3c1c0fc0 lui& gp,0xfc0
& 400de8: 279c79dc addiu&&& gp,gp,31196
addu gp,gp,t9
& 400df0: 27bdffe0 addiu&&& sp,sp,-32
& 400df4: afbc0010 sw&& gp,16(sp)
& 400df8: afbf001c sw&& ra,28(sp)
& 400dfc: afbc0018 sw&& gp,24(sp)
& print_backtrace ();&
& 400e00: 8f9980a4 lw&& t9,-32604(gp)
& 400e10: 8fbc0010 lw&& gp,16(sp)
& return 0;
& 400e14: 8fbf001c lw&& ra,28(sp)
move v0,zero
& 400e1c: 03e00008 jr&& ra
& 400e20: 27bd0020 addiu&&& sp,sp,32
You need to use the unwinder.
#include &unwind.h&
#include &stdio.h&
static _Unwind_Reason_Code
backtrace_helper (struct _Unwind_Context *ctx, void *a)
& void *ip = (void*)_Unwind_GetIP (ctx);
& fprintf (stdout, "&& %p/n", ip);
& return _URC_NO_REASON;
print_backtrace (void)
& _Unwind_Backtrace (backtrace_helper, NULL);
main (int argc, char **argv)
& print_backtrace ();&
& return 0;
该回答解释了上面的问题,提出用_Unwind_Backtrace函数来显示caller的地址,其实就MIPS而言对于单枝函数(没有子函数调用的函数)只要读ra寄存器的值就可以了,对于非单枝函数需要从堆栈里恢复出ra并显示。同样的问题这个函数也没有做向前的追溯。
For that to work, you must compile all the code with -fexceptions.
You could also try compiling all the code with -fno-omit-framepointer and writing your own unwinder.& I posted such an unwinder to java-patches@gcc.gnu.org several years ago.& Later versions of GCC are starting to do optimizations in the function prolog that make unwinding without the unwinder meta-data very difficult.
David Daney
该回答给出了2个GCC的参数,也是回答了上面的问题。
根据MIPS寄存器定义和GCC生成的机器码可以得到网上描述的&MIPS不支持C函数的帧结构&。
我的理解是和x86的ESP和EBP寄存器比,MIPS的确是无法直观的从寄存器里找到当前情况下堆栈的底部,每个函数对应的栈的尺寸是由GCC计算出的,函数返回时的栈的恢复也是通过立即数的方式通过指令来实现,如(addiu&&& sp,sp,40),这样我们做BackTrace最重要的一个问题就是确定每级函数的堆栈尺寸。
我觉得要确定每级函数的堆栈尺寸,只能通过解析机器码来实现。凑巧发现netbsd系统在内核代码中实现了对MIPS体系结构backtrace的支持,现在来分析下核心代码。
代码的全路径:
/src/sys/arch/mips/mips/trap.c
#define&& MIPS_JR_RA&&&&&&&&& 0x03e00008&&&&&&&&& /* instruction code for jr ra */
#define&& MIPS_JR_K0&&&&&&&&& 0x&&&&&&&&& /* instruction code for jr k0 */
#define&& MIPS_ERET 0x&&&&&&&&& /* instruction code for eret */
* Do a stack backtrace.
* (*printfn)()& prints the output to either the system log,
* the console, or both.
stacktrace_subr(mips_reg_t a0, mips_reg_t a1, mips_reg_t a2, mips_reg_t a3,
&&& vaddr_t pc, vaddr_t sp, vaddr_t fp, vaddr_t ra,
&&& void (*printfn)(const char*, ...))
&&&&&&&&& vaddr_t va,
&&&&&&&&& unsigned instr,
&&&&&&&&& InstF
&&&&&&&&& int more,
&&&&&&&&& unsigned int frames =& 0;
&&&&&&&&& int foundframesize = 0;
#ifdef DDB
&&&&&&&&& db_expr_
&&&&&&&&& db_sym_
/* Jump here when done with a frame, to start a new one */
&&&&&&&&& stksize = 0;
&&&&&&&&& subr = 0;
&&&&&&&&& if (frames++ & 100) {
&&&&&&&&&&&&&&&&&&& (*printfn)("/nstackframe count exceeded/n");
&&&&&&&&&&&&&&&&&&& /* return breaks stackframe-size heuristics with gcc -O2 */
&&&&&&&&&&&&&&&&&&&&&&&&&& /*XXX*/
&&&&&&&&& }
&&&&&&&&& /* check for bad SP: could foul up next frame */
&&&&&&&&& if (sp & 3 || (intptr_t)sp &= 0) { /* 首先堆栈值应该4字节地址对齐,其次bit31应该为1表示内核空间*/
&&&&&&&&&&&&&&&&&&& (*printfn)("SP 0x%x: not in kernel/n", sp);
&&&&&&&&&&&&&&&&&&& ra = 0;
&&&&&&&&&&&&&&&&&&& subr = 0;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&& }
&&&&&&&&& /* Check for bad PC */
&&&&&&&&& if (pc & 3 || (intptr_t)pc &= 0 || (intptr_t)pc &= (intptr_t)edata) {
&&&&&&&&&&&&&&&&&&& (*printfn)("PC 0x%x: not in kernel space/n", pc);
&&&&&&&&&&&&&&&&&&& ra = 0;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&& }
#ifdef DDB
&&&&&&&&& /*
* Check the kernel symbol table to see the beginning of
* the current subroutine.
&&&&&&&&& diff = 0;
&&&&&&&&& sym = db_search_symbol(pc, DB_STGY_ANY, &diff);
&&&&&&&&& if (sym != DB_SYM_NULL && diff == 0) {
&&&&&&&&&&&&&&&&&&& /* check func(foo) __attribute__((__noreturn__)) case */
&&&&&&&&&&&&&&&&&&& instr = kdbpeek(pc - 2 * sizeof(int));
&&&&&&&&&&&&&&&&&&& i.word =
&&&&&&&&&&&&&&&&&&& if (i.JType.op == OP_JAL) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& sym = db_search_symbol(pc - sizeof(int),
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&& DB_STGY_ANY, &diff);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& if (sym != DB_SYM_NULL && diff != 0)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& diff += sizeof(int);
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&& }
&&&&&&&&& if (sym == DB_SYM_NULL) {
&&&&&&&&&&&&&&&&&&& ra = 0;
&&&&&&&&&&&&&&&&&&&
&&&&&&&&& }
&&&&&&&&& va = pc -
#else /* 基本来到这里,我们没有这个存放符号信息的数据库 */
&&&&&&&&& /*
* Find the beginning of the current subroutine by scanning backwards
* from the current PC for the end of the previous subroutine.
&&&&&&&&& &* XXX This won't work well because nowadays gcc is so aggressive
*&&&& as to reorder instruction blocks for branch-predict.
*&&&& (i.e. 'jr ra' wouldn't indicate the end of subroutine)
&&&&&&&&& /* 这里向前搜索OPCODE,直到找到0x03e00008或者产生地址越界(超出了代码段最小可能地址verylocore),这样做是不可靠的,因为是通过搜索上一个函数的特征机器码来确定当前函数的顶部,所以一个假设前提是前面还有函数*/
&&&&&&&&& va =
&&&&&&&&& do {
&&&&&&&&&&&&&&&&&&& va -= sizeof(int);
&&&&&&&&&&&&&&&&&&& if (va &= (vaddr_t)verylocore)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&& instr = kdbpeek(va);
&&&&&&&&&&&&&&&&&&& if (instr == MIPS_ERET)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& goto mips3_
&&&&&&&&& } while (instr != MIPS_JR_RA && instr != MIPS_JR_K0);
&&&&&&&&& /* skip back over branch & delay slot */
&&&&&&&&& va += sizeof(int); /*跳过延时槽*/
mips3_eret:
&&&&&&&&& va += sizeof(int); /*跳过JR_RA指令 */
&&&&&&&&& /* skip over nulls which might separate .o files */
&&&&&&&&& while ((instr = kdbpeek(va)) == 0)
&&&&&&&&&&&&&&&&&&& va += sizeof(int); /* 跳过无用的空指令 */
&&&&&&&&& subr = /* 得到当前函数的首地址 */
&&&&&&&&& /* scan forwards to find stack size and any saved registers */
&&&&&&&&& stksize = 0;
&&&&&&&&& more = 3;
&&&&&&&&& mask = 0;
&&&&&&&&& foundframesize = 0;
&&&&&&&&& for (va = va += sizeof(int),
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&& more = (more == 3) ? 3 : more - 1) {
&&&&&&&&&&&&&&&&&&& /* stop if hit our current position */
&&&&&&&&&&&&&&&&&&& if (va &= pc)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&& instr = kdbpeek(va);
&&&&&&&&&&&&&&&&&&& i.word =
&&&&&&&&&&&&&&&&&&& switch (i.JType.op) {
&&&&&&&&&&&&&&&&&&& case OP_SPECIAL:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& switch (i.RType.func) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case OP_JR:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case OP_JALR:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& more = 2; /* stop after next instruction */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case OP_SYSCALL:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case OP_BREAK:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& more = 1; /* stop now */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& };
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&& case OP_BCOND:
&&&&&&&&&&&&&&&&&&& case OP_J:
&&&&&&&&&&&&&&&&&&& case OP_JAL:
&&&&&&&&&&&&&&&&&&& case OP_BEQ:
&&&&&&&&&&&&&&&&&&& case OP_BNE:
&&&&&&&&&&&&&&&&&&& case OP_BLEZ:
&&&&&&&&&&&&&&&&&&& case OP_BGTZ:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& more = 2; /* stop after next instruction */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&& case OP_COP0:
&&&&&&&&&&&&&&&&&&& case OP_COP1:
&&&&&&&&&&&&&&&&&&& case OP_COP2:
&&&&&&&&&&&&&&&&&&& case OP_COP3:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& switch (i.RType.rs) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case OP_BCx:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case OP_BCy:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& more = 2; /* stop after next instruction */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& };
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&& case OP_SW:/* 解析存放在堆栈上的有用数据:包括4个传递参数的寄存器、帧指针、函数返回地址*/
#if !defined(__mips_o32)
&&&&&&&&&&&&&&&&&&& case OP_SD:
&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& size_t size = (i.JType.op == OP_SW) ? 4 : 8;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& /* look for saved registers on the stack */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& if (i.IType.rs != 29)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& /* only restore the first one */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& if (mask & (1 && i.IType.rt))
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& mask |= (1 && i.IType.rt);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& switch (i.IType.rt) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case 4: /* a0 */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& a0 = kdbrpeek(sp + (short)i.IType.imm, size);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case 5: /* a1 */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& a1 = kdbrpeek(sp + (short)i.IType.imm, size);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case 6: /* a2 */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& a2 = kdbrpeek(sp + (short)i.IType.imm, size);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case 7: /* a3 */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& a3 = kdbrpeek(sp + (short)i.IType.imm, size);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case 30: /* fp */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& fp = kdbrpeek(sp + (short)i.IType.imm, size);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& case 31: /* ra */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ra = kdbrpeek(sp + (short)i.IType.imm, size);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&& case OP_ADDI:
&&&&&&&&&&&&&&&&&&& case OP_ADDIU: /* 这里来分析堆栈的尺寸,是一个类似于addiu&&& sp,sp,-24的指令,我们要将立即数取出,并负负得正 */
#if !defined(__mips_o32)
&&&&&&&&&&&&&&&&&&& case OP_DADDI:
&&&&&&&&&&&&&&&&&&& case OP_DADDIU:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& /* look for stack pointer adjustment */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& if (i.IType.rs != 29 || i.IType.rt != 29)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& /* don't count pops for mcount */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& if (!foundframesize) {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& stksize = - ((short)i.IType.imm);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& foundframesize = 1;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&& }
&&&&&&&&& (*printfn)("%s+%"PRIxVADDR" (%"PRIxREGISTER",%"PRIxREGISTER",%"PRIxREGISTER",%"PRIxREGISTER") ra %"PRIxVADDR" sz %d/n",
&&&&&&&&&&&&&&&&&&& fn_name(subr), pc - subr, a0, a1, a2, a3, ra, stksize);
&&&&&&&&& if (ra) {
&&&&&&&&&&&&&&&&&&& if (pc == ra && stksize == 0)/* 出现堆栈长度为零并且当前程序指针为返回地址,则出现循环调用,为异常情况,应直接返回 */
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& (*printfn)("stacktrace: loop!/n");
&&&&&&&&&&&&&&&&&&& else {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& pc =
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& sp +=
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ra = 0;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&& }
&&&&&&&&& } else {/* 返回地址为零表示已经追溯到最顶层 */
&&&&&&&&&&&&&&&&&&& if (curlwp)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& (*printfn)("User-level: pid %d.%d/n",
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&curlwp-&l_proc-&p_pid, curlwp-&l_lid);
&&&&&&&&&&&&&&&&&&& else
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& (*printfn)("User-level: curlwp NULL/n");
&&&&&&&&& }
下面演示将上面的函数移植到Linux下,应用程序出现异常时的BackTrace显示
应用程序代码:
#include &stdio.h&
#include &stdlib.h&
#include &signal.h&
extern int sig_set(int signo);
int func_a(unsigned char* a, unsigned char * b, int c, int d);
int func_b(unsigned char* a);
int func_c(unsigned char* a);
int func_a(unsigned char* a, unsigned char * b, int c, int d)
&&& func_b(a);
&&& return 0;
int func_b(unsigned char* a)
&&& func_c(a);
&&& return 0;
int func_c(unsigned char* a)
&&& *a = "Hello";
&&& return 0;
int main(int argc, char* argv[])
&&& unsigned char*
&&& unsigned char buffer[128];
&&& a = NULL;
&&&&&&& if( sig_set(SIGSEGV) != 0)
&&&&&&&&&&&&&&& printf("cannot catch SIGSEGV/n");
&&&&&&& if( sig_set(SIGILL) != 0)
&&&&&&&&&&&&&&& printf("cannot catch SIGILL/n");
&&&&&&& printf("trying to catch SIGFPE/n");
&&&&&&& if( sig_set(SIGFPE) != 0)
&&&&&&&&&&&&&&& printf("cannot catch SIGFPE/n");
&&&&&&& printf("trying to catch SIGBUS/n");
&&&&&&& if( sig_set(SIGBUS) != 0)
&&&&&&&&&&&&&&& printf("cannot catch SIGBUS/n");
&&& func_a(a, buffer, 2, 3);
&&& return 0;
先注册了4个信号SIGSEGV、SIGILL、SIGFPE、SIGBUS用自己的处理函数来处理。
在函数func_c调用的时候会出现异常,因为a的地址为NULL,这时将整个函数调用的过程显示出来,输入如下:
fSegvHandler default sigNo [11]
&pc=00400a84 cause
&d00::7fff7bd0 d02:0:
&d04::7fff7d08 d06::
&d08::0000000a d10::
&d12:::0000000a d15:
&d16::7fff7df4 d18:0:
&d20:00400a9c d21::ffffffff d23:
&d24::00400a4c d26::
&d28::7fff7c88 d30:7fff7c88 d31:00400a30
&k1(d27): gp(d28):
&sp(d29):7fff7c88
&fp(d30):7fff7c88 ra(d31):00400a30
&hi:&&&& lo:
Calling backtrace:
Func [400a4c] PC [400a84] Arg0~3 (0,7fff7d08,2,3) RetAddr [400a30] stackSize [16]
Func [4009f4] PC [400a30] Arg0~3 (0,7fff7d08,2,3) RetAddr [4009d8] stackSize [40]
Func [400990] PC [4009d8] Arg0~3 (0,7fff7d08,2,3) RetAddr [400c38] stackSize [40]
Func [400a9c] PC [400c38] Arg0~3 (0,7fff7d08,2,3) RetAddr [2ab18b50] stackSize [176]
Func [2ab189b0] PC [2ab18b50] Arg0~3 (0,7fff7d08,2,3) RetAddr [400790] stackSize [32]
Func [400790] PC [400790] Arg0~3 (0,7fff7d08,2,3) RetAddr [0] stackSize [0]
Segmentation fault
上面输出的结果可以和实际情况对应起来:
这里是函数调用栈上各个函数的基地址
-bash-3.00$ mips_fp_be-objdump -t test1 | grep 400a4c
00400a4c g&&&& F .text& &&&&&&&&&&&&& func_c
-bash-3.00$ mips_fp_be-objdump -t test1 | grep 4009f4
g&&&& F .text& &&&&&&&&&&&&& func_b
-bash-3.00$ mips_fp_be-objdump -t test1 | grep 400990
g&&&& F .text& &&&&&&&&&&&&& func_a
-bash-3.00$ mips_fp_be-objdump -t test1 | grep 400a9c
00400a9c g&&&& F .text& &&&&&&&&&&&&& main
-bash-3.00$ mips_fp_be-objdump -t test1 | grep 400790
g&&&& F .text& &&&&&&&&&&&&& __start
PC表示当前函数执行的地址,RetAddr为函数返回地址(和上级函数的PC对应)
例如第一行的输出:
Func [400a4c] PC [400a84] Arg0~3 (0,7fff7d08,2,3) RetAddr [400a30] stackSize [16]
对应于下面反汇编出来的代码,看的更清楚。
int func_c(unsigned char* a)
& 400a4c:&& 3c1c0fc0 && lui gp,0xfc0
& 400a50:&& 279c75f4 && addiu&& gp,gp,30196
& 400a54:&&
&& addu&&& gp,gp,t9
& 400a58:&& 27bdfff0 && addiu&& sp,sp,-16
& 400a5c:&& afbc0000 && sw& gp,0(sp)
& 400a60:&& afbe000c && sw& s8,12(sp)
& 400a64:&& afbc0008 && sw& gp,8(sp)
& 400a68:&& 03a0f021 && move&&& s8,sp
& 400a6c:&& afc40010 && sw& a0,16(s8)
&&& *a = "Hello";
& 400a70:&& 8fc30010 && lw& v1,16(s8)
& 400a74:&& 8f828018 && lw& v0,-32744(gp)
& 400a78:&&
& 400a7c:&& 24421ee0 && addiu&& v0,v0,7904
& 400a80:&&
& 400a84:&& a0620000 && sb& v0,0(v1)
&&& return 0;
& 400a88:&&
&& move&&& v0,zero
& 400a8c:&& 03c0e821 && move&&& sp,s8
& 400a90:&& 8fbe000c && lw& s8,12(sp)
& 400a94:&& 03e00008 && jr& ra
& 400a98:&& 27bd0010 && addiu&& sp,sp,16
int func_b(unsigned char* a)
& 4009f4:&& 3c1c0fc0 && lui gp,0xfc0
& 4009f8:&& 279c764c && addiu&& gp,gp,30284
& 4009fc:&&
&& addu&&& gp,gp,t9
& 400a00:&& 27bdffd8 && addiu&& sp,sp,-40
& 400a04:&& afbc0010 && sw& gp,16(sp)
& 400a08:&& afbf0020 && sw& ra,32(sp)
& 400a0c:&& afbe001c && sw& s8,28(sp)
& 400a10:&& afbc0018 && sw& gp,24(sp)
& 400a14:&& 03a0f021 && move&&& s8,sp
& 400a18:&& afc40028 && sw& a0,40(s8)
&&& func_c(a);
& 400a1c:&& 8fc40028 && lw& a0,40(s8)
& 400a20:&& 8f998030 && lw& t9,-32720(gp)
& 400a24:&&
& 400a28:&&
&& jalr&&& t9
& 400a2c:&&
& 400a30:&& 8fdc0010 && lw& gp,16(s8)
&&& return 0;
& 400a34:&&
&& move&&& v0,zero
& 400a38:&& 03c0e821 && move&&& sp,s8
& 400a3c:&& 8fbf0020 && lw& ra,32(sp)
& 400a40:&& 8fbe001c && lw& s8,28(sp)
& 400a44:&& 03e00008 && jr& ra
& 400a48:&& 27bd0028 && addiu&& sp,sp,40
阅读(...) 评论()

我要回帖

更多关于 集装箱gp是什么意思 的文章

 

随机推荐