机械设计.ppt

上传人:文库蛋蛋多 文档编号:2672385 上传时间:2023-02-22 格式:PPT 页数:65 大小:1.09MB
返回 下载 相关 举报
机械设计.ppt_第1页
第1页 / 共65页
机械设计.ppt_第2页
第2页 / 共65页
机械设计.ppt_第3页
第3页 / 共65页
机械设计.ppt_第4页
第4页 / 共65页
机械设计.ppt_第5页
第5页 / 共65页
点击查看更多>>
资源描述

《机械设计.ppt》由会员分享,可在线阅读,更多相关《机械设计.ppt(65页珍藏版)》请在三一办公上搜索。

1、第4章 MCS-51汇编语言程序设计,4.1 汇编语言程序设计概述 4.1.1 机器语言、汇编语言和高级语言用于程序设计的语言基本上分为3种:机器语言、汇编语言和高级语言。1.机器语言 二进制代码表示的指令、数字和符号简称为机器语言 不易懂,难记忆,易出错。,2汇编语言 英文助记符表示的指令称为符号语言或汇编语言汇编语言特点:面向机器的语言,程序设计员须对MCS-51的硬件有相当深入的了解。助记符指令和机器指令一一对应,用汇编语言编写的程序效率高,占用存储空间小,运行速度快,用汇编语言能编写出最优化的程序。,能直接管理和控制硬件设备(功能部件),它能处理中断,也能直接访问存储器及I/O接口电路

2、。汇编语言和机器语言都脱离不开具体机器的硬件,均是面向“机器”的语言,缺乏通用性。3高级语言不受具体机器的限制,使用了许多数学公式和数学计算上的习惯用语,非常擅长于科学计算。常用的如BASIC、FORTRAN以及C语言等。高级语言优点:通用性强,直观、易懂、易学,可读性好。使用C语言(C51)、PL/M语言来进行MCS-51的应用程序设计。对于程序的空间和时间要求很高的场合,汇编语言仍是必不可缺的。,C语言和汇编语言混合编程 在很多需要直接控制硬件的应用场合,则更是非用汇编语言不可 使用汇编语言编程,是单片机程序设计的基本功之一4.1.2 汇编语言语句的种类和格式两种基本类型:指令语句和伪指令

3、语句(1)指令语句已在第3章介绍每一条指令语句在汇编时都产生一个指令代码机器代码(2)伪指令语句 是为汇编服务的。在汇编时没有机器代码与之对应。,MCS-51的汇编语言的四分段格式如下:标号字段 操作码字段 操作数字段 注释字段例4-1 下面是一段汇编语言程序的四分段书写格式 基本语法规则:1标号字段是语句所在地址的标志符号 标号字段 操作码字段 操作数字段 注释字段 START:MOV A,#00H;0A MOV R1,#10;10R1 MOV R2,#00000011B;3R2 LOOP:ADD A,R2;(A)+(R2)A DJNZ R1,LOOP;R1内容减1不 为零,则循环 NOP

4、HERE:SJMP HERE,2美元符号$的使用用于表示该转移指令操作码所在的地址。例如,如下指令:JNB F0,$与如下指令是等价的:HERE:JNB F0,HERE 再如:HERE:SJMP HERE可写为:SJMP$,4.2 汇编语言源程序的汇编汇编语言源程序“翻译”成机器代码(指令代码)的过程称为“汇编”。汇编可分为手工汇编和机器汇编两类:4.2.1 手工汇编人工查表翻译指令。但遇到的相对转移指令的偏移量的计算,要根据转移的目标地址计算偏移量,不但麻烦,且容易出错。4.2.2 机器汇编用编辑软件进行源程序的编辑。编辑完成后,生成一个ASCII码文件,扩展名为“.ASM”。然后在微计算机

5、上运行汇编程序,把汇编语言源程序翻译成机器代码。,交叉汇编汇编后的机器代码是在另一台计算机(这里是单片机)上运行。MCS-51单片机的应用程序的完成,应经过三个步骤;(1)在微计算机上,运行编辑程序进行源程序的输入 和编辑;(2)对源程序进行交叉汇编得到机器代码;(3)通过微计算机的串行口(或并行口)把机器代码传送到用户样机(或在线仿真器)进行程序的调试和运行。反汇编分析现成产品的程序,要将二进制的机器代码语言程序翻译成汇编语言源程序。,4.3 汇编语言实用程序设计4.3.3 查表程序设计 数据补偿、修正、计算、转换等各种功能,具有程序简单、执行速度快等优点。查表就是根据自变量x,在表格中寻找

6、y,使y=f(x)。执行查表指令时,发出读程序存储器选通脉冲/PSEN。在MCS-51的指令系统中,给用户提供了两条极为有用的查表指令:MOVC A,A+DPTR MOVC A,A+PC指令“MOVC A,A+DPTR”完成把A中的内容作为一个无符号数与DPTR中的内容相加,所得结果为某一程序,。指令执行完,PC的内容不发生变化,仍指向查表指令的下一条指令。优点在于预处理较少且不影响其它特殊功能寄存器的值,所以不必保护其它特殊功能寄存器的原先值。缺点在于该表格只能存放在这条指令的地址X3X2X1X0以下的00FFH之中。表格所在的程序空间受到了限制。,例4-1 子程序的功能为:根据累加器A中的

7、数x(09之间)查x的平方表y,根据x的值查出相应的平方y。x和y均为单字节数。地 址 子程序Y3Y2Y1Y0 ADD A,#01H Y3Y2Y1Y0+2 MOVC A,A+PCY3Y2Y1Y0+3 RET Y3Y2Y1Y0+4 DB 00H,01H,04H,09H,10H DB 19H,24H,31H,40H,51H第1条指令 ADD A,#01H 的作用是加上偏移量,可以根据A的内容查出X对应的平方。,MOVC A,A+DPTR 这条指令的应用范围较为广泛,一般情况下,大多使用该指令,使用该指令时不必计算偏移量,使用该指令的优点是表格可以设在64K程序存储器空间内的任何地方,而不像 MOV

8、C A,A+PC那样只设在PC下面的256个单元中,使用较方便。上面的程序可改成如下形式:,PUSH DPH;保存DPH PUSH DPL;保存DPL MOV DPTR,#TAB1 MOVC A,A+DPTR POP DPL;恢复DPL POP DPH;恢复DPH RETTAB1:DB 00H,01H,04H,09H,10H DB 19H,24H,31H,40H,51H例4-2 在一个以MCS-51为核心的温度控制器中,温度传感器输出的电压与温度为非线性关系,传感器输出的电压已由A/D转换为10位二进制数。根据测得的不同温度下的电压值数据构成一个表,表中放温度,值y,x为电压值数据。设测得的电

9、压值x放入R2R3中,根据电压值x,查找对应的温度值y,仍放入R2R3中。本例的x和y均为双字节无符号数。程序如下:LTB2:MOV DPTR,#TAB2 MOV A,R3 CLR C RLC A MOV R3,A XCH A,R2 RLC A XCH R2,A ADD A,DPL;(R2R3)+(DPTR)(DPTR),MOV DPL,A MOV A,DPH ADDC A,R2 MOV DPH,A CLR A MOVC A,A+DPTR;查第一字节 MOV R2,A;第一字节存入R2中 CLR A INC DPTR MOVC A,A+DPTR;查第二字节 MOV R3,A;第二字节存入R3中

10、 RET TAB2:DW;温度值表,例4-3 设有一个巡回检测报警装置,需对16路输入进行检测,每路有一最大允许值,为双字节数。运行时,需根据测量的路数,找出每路的最大允许值。看输入值是否大于最大允许值,如大于就报警。根据上述要求,编一个查表程序。取路数为x(0 x15),y为最大允许值,放在表格中。设进入查表程序前,路数x已放于R2中,查表后最大值y放于R3R4中。本例中的x为单字节数,y为双字节数。查表程序如下:TB3:MOV A,R2 ADD A,R2;(R2)*2(A)MOV R3,A;保存指针 ADD A,#6;加偏移量,MOVC A,A+PC;查第一字节XCH A,R3 ADD A

11、,#3 MOVC A,A+PC;查第二字节 MOV R4,ARET TAB3:DW 1520,3721,42645,7580;最大值;表 DW 3483,32657,883,9943 DW 10000,40511,6758,8931 DW 4468,5871,13284,27808,表格长度不能超过256个字节,且表格只能存放于MOVC A,A+PC指令以下的256个单元中。查表指令(MOVC A,A+PC、MOVC A,A+DPTR)的区别1)MOVC A,A+PC表格长度不能超过256个字节,且表格只能存放于MOVC A,A+PC指令以下的256个单元中。MOVC A,A+DPTR表格可以

12、设在64K程序存储器空间内的任何地方2)MOVC A,A+PC PC是执行完本条指令后,指向下一条指令的 地址,需加上偏移量 MOVC A,A+DPTR 不需要加偏移量。,3)根据表中指令的字节数不同,A分别乘以1、2或3,从表中取指令时,也要分1、2或3次进行。,单字节指令A=A1,双字节指令A=A2,基址+0,基址+1,基址+2,(A)=0对应的一条指令,(A)=1对应的一条指令,三字节指令A=A3,基址+3,基址+4,基址+5,4.3.5 数据极值查找程序设计在指定的数据区中找出最大值(或最小值)。进行数值大小的比较,从这批数据中找出最大值(或最小值)并存于某一单元中。例4-9 已知内部

13、RAM ADDR为起始的数据块内数据是无符号数,块长在LEN单元内,找出数据块中最大值并存入MAX单元。程序如下:,ORG 2000HLEN DATA 20HMAX DATA 22H MOV MAX,#00H;MAX单元清零 MOV R0,#ADDR;ADDR送R0LOOP:MOV A,R0;数块中某数送A CJNE A,MAX,NEXT1;A和(MAX)比较NEXT1:JC NEXT;若A(MAX),则NEXT MOV MAX,A;若A(MAX),则大数送MAXNEXT:INC R0;修改数据块指针0 DJNZ LEN,LOOP;若未完,则转LOOPHERE:SJMP HERE END,4.

14、3.6 数据排序程序设计升序排,降序排。仅介绍无符号数据升序排。冒泡法:相邻数互换的排序方法,类似水中气泡上浮。排序时从前向后进行相邻两个数的比较,次序与要求的顺序不符时,就将两个数互换;顺序符合要求不互换。假设有7个原始数据的排列顺序为:6、4、1、2、5、7、3。第一次冒泡的过程是:6、4、1、2、5、7、3;原始数据的排列4、6、1、2、5、7、3;逆序,互换4、1、6、2、5、7、3;逆序,互换 4、1、2、6、5、7、3;逆序,互换4、1、2、5、6、7、3;逆序,互换,4、1、2、5、6、7、3;正序,不互换4、1、2、5、6、3、7;逆序,互换,第一次冒泡结束如此进行,各次冒泡的

15、结果如下:第1次冒泡结果:4、1、2、5、6、3、7第2次冒泡结果:1、2、4、5、3、6、7第3次冒泡结果:1、2、4、3、5、6、7第4次冒泡结果:1、2、3、4、5、6、7;已完成排序第5次冒泡结果:1、2、3、4、5、6、7第6次冒泡结果:1、2、3、4、5、6、7 对于n个数,理论上应进行(n-1)次冒泡,有时不到(n-1)次就已完成排序。,如何判定排序是否已完成,看各次冒泡中是否有互换发生,如果有数据互换,则排序还没完成。在程序设计中,常使用设置互换标志的方法,该标志的状态表示在一次冒泡中是否有互换进行。例4-10 假设8个数连续存放在20H为首地址的内部RAM单元中,使冒泡法进行

16、升序排序编程。设R7为比较次数计数器,初值为07H。TR0为冒泡过程中是否有数据互换的状态标志,TR0=0表示无互换发生,TR=1表明有互换发生。按前述冒泡序算法,程序如下:,SORT:MOV R0,#20H;数据存储区首单元地址 MOV R7,#07H;各次冒泡比较次数 CLR TR0;互换标志清“0”LOOP:MOV A,R0;取前数 MOV 2BH,A;存前数 INC R0 MOV 2AH,R0;取后数 CLR C SUBB A,R0;前数减后数 JC NEXT;前数小于后数,不互换 MOV R0,2BH DEC R0 MOV R0,2AH;两个数交换位置 INC R0;准备下一次比较

17、SETB TR0;置互换标志NEXT:DJNZ R7,LOOP;返回,进行下一次比较 JB TR0,SORT;返回,进行下一次冒泡HERE:SJMP HERE;排序结束,4.3.7 散转移程序设计一、使用转移指令的散转程序 JMP A+DPTR 需根据某一单元的内容是0,1,n,来分别转向处理程序0,处理程序1,处理程序n。一个典型的例子就是当单片机系统中的键盘按下时,就会得到一个键值,根据不同的键值,跳向不同的键处理程序入口。对于这种情况,可用直接转移指令(LJMP或AJMP指令)组成一个转移表,利用间接转移指令实现分支转移,例4-12 根据寄存器R2的内容,转向各个处理程序PRGX(X=0

18、n)。(R2)=0,转PRG0(R2)=1,转PRG1(R2)=n,转PRGn,JMP1:MOV DPTR,#TBJ1 MOV A,R2 ADD A,R2;(R2)*2(A)JNC NADD INC DPH;(R2)*2 256NADD:JMP A+DPTRTBJ1:AJMP PRG0 AJMP PRG1 AJMP PRGn,二、使用地址偏移量的散转程序例 按R2的内容转向6个处理程序JMP3:MOV A,R2 MOV DPTR,#TBJ3 MOVC A,A+DPTR;从表中读取变址 JMP A+DPTRTBJ3:DB PRG0-TBJ3 DB PRG1-TBJ3.DB PRG5-TBJ3PR

19、G0:处理程序0PRG1:处理程序1PRG2:处理程序2PRG3:处理程序3PRG4:处理程序4PRG5:处理程序5,4.3.8 循环程序设计 计数循环结构DJNZ Rn,rel;工作寄存器作控制计数器1、单循环定时程序例 MOV R5,#TIMELOOP:NOP 1T NOP 1T DJNZ R5,LOOP 2T循环体为4T,若晶振为6MHz,则T=12/fosc=2s一次循环延迟时间:4*T=8s程序的延迟时间:8*TIME(s)该程序最大延迟时间:256*8=2048(s),2,多重循环定时例4-16 50ms延时程序。延时程序与MCS-51指令执行时间有很大的关系。在使用12MHz晶振

20、时,一个机器周期为1s,执行一条DJNZ指令的时间为2s。这时,可用双重循环方法写出下面如下的延时50ms的程序:DEL:MOV R7,#200DEL1:MOV R6,#125 DEL2:DJNZ R6,DEL2;125*2=250s DJNZ R7,DEL1;0.25ms*200=50ms RET,以上延时程序不太精确,它没有考虑到除“DJNZ R6,DEL2”指令外的其它指令的执行时间,如把其它指令的执行时间计算在内,它的延时时间为:DEL:MOV R7,#200 1TDEL1:MOV R6,#125 1TDEL2:DJNZ R6,DEL2;125*2=250s 2T DJNZ R7,DE

21、L1 2T(250+1+2)*200+1=50.301ms 如果要求比较精确的延时,可按如下修改:DEL:MOV R7,#200 1TDEL1:MOV R6,#123 1T NOP 1TDEL2:DJNZ R6,DEL2;123*2T DJNZ R7,DEL1;(1+1+123*2+2)*200+1=50001T=500001s=50.001ms实际延迟时间为50.001ms,注意。软件延时程序,不允许有中断,否则将严重影响定时的准确性。,采用增减指令对定时程序进行微调 MOV R0,#TIME 1T LOOP:ADD A,R1 1T INC DPTR 2T DJNZ R0,LOOP 2T在6

22、MHz晶振下,机器周期T=12/fosc=2s定时时间为:5*2*TIME(s)假设定时时间要求为24s,可以调整循环体的机器周期。,MOV R0,#TIME 1T LOOP:ADD A,R1 1T INC DPTR 2T NOP 1T DJNZ R0,LOOP 2T使TIME=2定时时间=6*2s*2=24s,4.3.8 定点数运算程序设计,1、定点数的表示法1)原码:符号位=0 正数 符号位=1 负数加减运算时,必须按符号位的不同执行不同的运算。正数:N补=N原2)补码:N补=数值位取反+1 负数:=2n-数值 n是整数的位数 补码可直接带符号位进行运算,用OV位表示溢出与否,补码表示法的

23、优点是加减运算方便:(83)10+(-4)10=(01010011)2+(11111100)2=(01001111)2=(79)10补码表示的数在执行乘除运算时,先转换成原码,在执行原码乘除,最后把积转换成补码,例 双字节数取补子程序(R4R5)取补(R4R5)CMPT:MOV A,R5 CPL A ADD A,#1 MOV R5,A MOV A,R4 CPL A ADDC A,#0 MOV R4,A RET,2.带符号数的移位带符号数进行算数移位时,必须保持最高位不变。(1)正数:左移右移都移入0(2)负数:原码表示:符号位不变,左移右移 都移入0 补码表示:符号位不变,右移移入 1,左移移

24、入0例 双字节原码左移一位子程序。(R2R3)左移一位(R2R3),MOV A,R3CLR C;保证让左移移入0RLC AMOV R3,AMOV A,R2RLC AMOV A.7,C;恢复符号位MOV R2,A,R2,R3,C,0,符号位不变,例 双字节原码右移一位子程序(R2R3)右移一位(R2R3)0MOV A,R2MOV C,A.7;保护符号位CLR A.7;移入0RRC AMOV R2,AMOV A,R3RRC AMOV R3,A,R2,R3,C,C,符号位不变,A(R2),C,符号位,0,例 双字节补码右移一位子程序功能(R2R3)右移一位(R2R3)MOV A,R2MOV C,A.

25、7;保护符号位RRC A;移入符号位MOV R2,AMOV A,R3RRC AMOV R3,A,R2,R3,C,符号位不变,1,C,A(R2),C,符号位,1,三、定点数加减运算原码的加减运算需根据符号位和不同的运算进行分类操作。补码加减运算非常方便,一般采用补码进行加减运算。例 双字节补码加法子程序(R2R3)+(R6R7)(R4R5),MOV A,R3ADD A,R7MOV R5,AMOV A,R2ADDC A,R6MOV R4,A,四、定点数乘法运算1)无符号数二进制乘法A=1011 B=1001 1011 1001 1011 0000 0000+1011 1100011 乘积A*B,乘

26、数左移与部分积相加部分积右移+被乘数。,算法:从低位开始检查各个乘数的位数(乘数右移)若乘数位数为1,部分积右移+被乘数部分积。若乘数位数为0,部分积右移部分积。,2)MCS-51快速乘法把MCS51的单字节运算扩展为双字节的乘法计算原理 R2 R3 R6 R7 R3R7H R3R7L R2R7H R2R7L R3R6H R3R6L R2R6H R2R6L R4 R5 R6 R7,例 无符号双字节快速乘法(R2R3)*(R6R7)(R4R5R6R7)MOV A,R3 MOV B,R7 MUL AB;R3R7 BAXCH A,R7 R7=R3R7LMOV R5,B;B=R5=R3R7HMOV B

27、,R2MUL AB R2R7 BAADD A,R5 A=R2R7L+R3R7HMOV R4,A R4=R2R7L+R3R7H CLR AADDC A,B MOV R5,A;(R5)=R2R7H,4.3.9 码制转换程序设计 在单片机应用程序的设计中,经常涉及到各种码制的转换问题。在单片机系统内部经常采用二进制码。在输入/输出中,按照人的习惯均采用代表十进制数的BCD码表示。此外,打印机要打印某数字字符,则需要将该数字的二进制码转换为该字符的ASCII码。转换类型包括:二进制码与ASCII码之间的转换 二进制与BCD码之间的转换 一、二进制码与ASCII码之间的转换 由ASCII码字符表可知,0

28、9的ASCII码为30H39H,AF的ASCII码为41H46H,例 R0的低4位是一个二进制数,表示(0F),把它数码转换为ASCII代码并存入R0说明:二进制+30H=其ASCII代码 二进制 9;二进制+40H=其ASCII代码 二进制 9;,三种方法:1)若R0 9 R0+30HR0;若R0 9 R0+37HR0,2)利用DAA指令,3)查表,方法一:,ORG 0400HMOV A,R0;取转换值送AANL A,#0FH;屏蔽高四位ADD A,#90H;A中内容+90HDA A;十进制调整ADDC A,#40H;A中内容+40HDA A;十进制调整MOV R0,A;存转换结果SJMP$

29、;结束END,方法二:利用DA A指令,方法三:查表ORG 0400HMOV A,R0 ANL A,#0FH;屏蔽高4位ADD A,#03H;地址调整MOVC A,A+PC;查表MOV R0,A;存结果SJMP,$ASCTAB:DB 0,1,2,3,4 DB 5,6,7,8,9 DB A,B,C,D,E,F END,多位十六进制数转换成ASCII码思路:,低四位转换成ASCII高四位转换成ASCII,循环体完成一个字节十六进制数的转换,字节-1不为0转移,结束,例 多位十六进制数转换为ASCII码入口:(R0)=十六进制数低位地址指针(R2)=字节数 出口:(R1)=ASCII码地址指针,二、

30、二进制码到BCD码的转换二进制,1111001B=121D,BCD码(一个字节表示一个BCD码),00000001,00000010,1,2,00000001,1,压缩BCD码(一个字节表示2个BCD码),方法一:通过除以1000、100、10等10的次幂,获得千、百、十位数,例 8位二进制数转换成BCD数(A)为二进制数,R0为十位数和个位数地址指针(压缩的BCD码)MOV B,#100DIV AB;(A)=百位数MOV R0,A;存入RAMINC R0;MOV A,#10XCH A,BDIV A,B;(A)=十位数,(B)=个位数SWAP A ADD A,B;合成到(A)MOV R0,A

31、存入RAM,该方法的缺点:被转换数较大时,需进行多字节除法运算,运算速度较慢,程序缺乏通用性,方法二:Y=an2n+an-12n-1+an-22n-2+a0=(an2)+an-1)2+an-2)2)2+a0(每次相加时进行BCD码调整),例 双字节二进制数转换为BCD数入口:(R2R3)为双字节16位二进制数出口:(R4R5R6为转换完的压缩BCD码)Y=a727+a626+a525+a0=(a72)+a6)2+a5)2)2+a0(每次相加时进行BCD码调整)计算结果2+R2R3的次高位计算结果,R2R3,C,二进制位数-1=0?,结束,R4R5R6清零,N,Y,Y=a727+a626+a52

32、5+a0=(a72)+a6)2+a5)2)2+a0,DA A 调整,例 双字节二进制数转换为BCD数入口:(R2R3)为双字节16位二进制数出口:(R4R5R6为转换完的压缩BCD码),R2R3,C,LOOP:CLR C MOV A,R3 RLC A MOV R3,A MOV A,R2 RLC A MOV R2,A,MOV A,R6ADDC A,R6DA A MOV R6,A,R6,R6,2,三、BCD码到二进制码的转换 BCD码有两种形式:一种是1个字节放1位BCD码,一种是压缩的BCD码,即1个字节放两位BCD码,可以节省存储单元。,BCD码,压缩BCD码,8,6,10111010B=86

33、D,二进制,00001000,00000110,8,6,10000110,例:(186)BCD=1102+8101+6,BCD码转换为二进制码的算法Y=an10n+an-110n-1+an-210n-2+a0=(an10)+an-1)10+an-2)10)10+a0例 四位BCD数转换成二进制数入口:BCD码放在a3、a2、a1、a0分别放在50H53H出口:二进制结果放在R3R4中Y=a3103+a2102+a1101+a0=(a310)+a2)10+a1)10+a0,R3清零R4千位BCD码,R3R4R3R410R0R0+1,R3R4R3R4+(R0),结束,R2-1=0?,R2是BCD码

34、的位数,R0是BCD码的起始地址指针,R3 R4 10 R4 10H R4 10L R3 10H R3 10L,MOV A,R4MOV B,#10MUL AB;B R4 10H A R4 10LMOV R4,A;R4 R4 10L MOV A,#10XCH A,B;A R4 10H B 10XCH A,R3;R3 R4 10H A R3MUL AB;B R3 10H A R3 10L,ADD A,R3;A R4 10H+R3 10LXCH A,R4;,总结1.二进制码到ASCII码的转换 1)二进制数小于9,加30H,否则加37H2)利用DA A指令,先加90H,再加40H查表(ASCII码到二进制的转换可采取上述方法1或3的逆过程)2.二进制码到BCD码的转换1)通过DIV指令分离出千位、百位和十位(只适用于二进制数不是太大的情况)2)类似二进制转十进制的方法,按权展开。编程时用迭代的方法,配合使用DA A指令。,3.BCD码到二进制码的转换 对BCD码的每位按权为10展开,编程时用迭代的方法Y=an10n+an-110n-1+an-210n-2+a0=(an10)+an-1)10+an-2)10)10+a0,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号