您好,欢迎访问三七文档
1第7章目标代码生成7.1汇编语言虚拟计算机模型7.2从四元式到汇编语言的翻译7.3一个简单目标代码生成器7.4静态地址分配2㈠任务将中间代码变换成目标代码,实现源程序的最后翻译。由于涉及到目标机器的系统结构,此阶段的工作最复杂。㈡目标代码的形式①已定位的机器语言代码编译后可立即执行。②待装配的机器语言代码模块目前大多数编译系统所产生的目标代码均为可重定位的机器指令。在执行前,将它和系统函数(源程序中使用)的机器指令连接成一个程序,对未确定的地址进行定位(用户程序为0地址空间),形成可执行的机器语言程序。在执行时,操作系统可将目标代码装入内存的任意位置。③汇编语言代码需经汇编程序翻译,将其转换成可执行的机器语言代码。由于硬件厂商提供机器的汇编程序,所以编译程序的目标代码通常为汇编语言形式。㈢目标代码生成要求①目标代码数与中间代码数的比值尽可能小(即目标代码数尽可能少)。②充分利用寄存器,减少访问内存的次数。③删除不必要的临时变量。37.1汇编语言虚拟计算机模型㈠内存①共有64k个字,1个字有16个二进制位(2Byte),内存地址标识为0-65535。②划分为256页,页号0-255,每页的长度为256个字,页内位移为0-255。③地址计算:页号*256+页内位移。④255页用作系统堆栈区。㈡寄存器①通用寄存器(2字节)共有4个,分别标记为R0、R1、R2、R3,用于存放操作数和计算结果,R3还可用于变址寻址。②标志寄存器FlagReg保存CMP指令比较结果。③堆栈寄存器TopReg(2字节)TopReg用作系统堆栈栈顶指针。4㈢指令系统(简单指令系统)指令格式:(定长、2字节)①操作码Read从键盘读一个字到第一地址。Write从第一地址写一个字到屏幕。Load从第二地址将字装入第一地址。Store将第一地址中的字存放到第二地址。Call控制转移到第二地址指定的内存单元,断点保留在系统堆栈中。Ret由系统堆栈获得断点,返回。Add将第一地址中的字加上第二地址中的字,结果保留第一地址中。SubMulDivCmp将第一地址中的字和第二地址中的字比较,由系统置位FlagReg。FlagReg=-1,表示第一地址中的字小于第二地址中的字。FlagReg=1,表示第一地址中的字大于第二地址中的字。FlagReg=0,表示第一地址中的字等于第二地址中的字。第二地址操作码第一地址寻址方式15-1211-109-87-0低8位用于第二地址的补充定义5JMP无条件转移到第二地址指定的内存单元。JMPNEG若FlagReg中的值<0,转移到第二地址指定的内存单元。JMPPOS若FlagReg中的值>0,转移到第二地址指定的内存单元。JMPZERO若FlagReg中的值=0,转移到第二地址指定的内存单元。HALT终止程序执行。②第一地址只能是寄存器(R0-R3)③第二地址有四种寻址方式直接地址寻址(M)LoadRi,MXXRi←(XX)XX范围00-FF(第0页),用16进制表示。寄存器寻址(R)LoadRi,RjRi←(Rj)寄存器(间址)寻址(@R)LoadRi,@RjRi←((Rj))直接数寻址(D)LoadRi,XXRi←XXXX范围00-FF,用16进制表示。变址寻址(C[R3])LoadRi,C[R3]Ri←(C*256+(R3))C为常数(范围00-FF),用16进制表示。6④指令分类零地址指令Ret、HaltA型一地址指令(无第二地址)Write、Read例:ReadR0//从键盘输入一个数,将其存放在R0中。B型一地址指令(无第一地址)Call、Jmp、JmpNeg、JmpZero、JmpPos例:Jmp2[R3]//无条件转移至地址2*256+(R3)单元二地址指令Load、Store、Add、Sub、Mul、Div、Cmp例:AddR3,1//R3的内容加1程序举例用汇编程序编写程序,求5的阶乘。LoadR0,1//R0的范围1..5LoadR1,1//初值为1,存放5!。AddR0,1MulR1,R0CmpR0,5JmpNegM2WriteR1Halt77.2从四元式到汇编语言的翻译㈠符号表、常数表和临时变量表的内存位置四元式中含有变量在符号表和临时变量表中的入口,以及常数在常数表中的地址,所以先确定符号表、临时变量表和常数表在内存中的位置,然后再讨论四元式的翻译。①无符号实常数表(第254页,按地址递减使用)起始地址:254*256+255=65279,每个实常数占用2个字(4Byte)。②无符号整常数表(第254页,按地址递增使用)起始地址:254*256=65024,每个整常数占用1个字(2Byte)。③符号表(第252、253页,按地址递减使用)起始地址:253*256+255=65023,每个标识符占用4个字(8Byte)。④临时变量表(第252、253页,按地址递增使用)起始地址:252*256=64512,每个临时变量占用4个字(8Byte)。注:四元式中最多允许出现512/4=128个不同的变量,包括临时变量在内。8虚拟内存示意图(共64K、分255页、每页255字节)255*256+255=65535系统堆栈区255255*256=65280无符号实常数表实常数表的起始地址为254*256+255254无符号整常数表整常数表的起始地址为254*256254*256=65024符号表符号表起始地址为253*256+255253253*256=64768临时变量表252临时变量表起始地址为252*256252*256=645129设源程序为:a=2+(+b+1),它的四元式代码为+&b0&T1+&T1&1&T2+&2&T2&T3=&T30&a假设整常数1在无符号整常数表中的地址为65024(254*256+0)整常数2在无符号整常数表中的地址为65025(254*256+1)变量a的符号表入口为65023(253*256+255)变量b的符号表入口为65019(253*256+251)临时变量T1的临时变量表入口为64512(252*256+0)临时变量T2的临时变量表入口为64516(252*256+4)临时变量T3的临时变量表入口为64520(252*256+8)实际四元式代码序列应为+65019064512+645126502464516+650256451664520=6452006502310㈡单个四元式的翻译四元式的翻译关键是确定地址,约定如下:指令的第一地址使用R0。指令的第二地址使用R3(兼作变址寄存器)。ARG1、ARG2为变量地址或常数地址,RESULT一定是变量地址。C1=ARG1/256、D1=ARG1%256。C2=ARG2/256、D2=ARG2%256。C3=RESULT/256、D3=RESULT%256。注:C1、C2、C3表示页码,D1、D2、D3表示页内位移。例1:(+,ARG1,ARG2,RESULT)设ARG1是变量在符号表或临时变量表入口,ARG2是常数在常数表中的地址。解:LoadR3,D1//R3←0LoadR0,C1[R3]//R0←(252*256+0)=(64512)LoadR0,@R0//R0的内容为存放临时变量T1值的地址LoadR3,D2//R3←0AddR0,C2[R3]//R0←(254*256+0)=(65024)LoadR3,D3//R3←4LoadR3,C3[R3]//R3←(252*256+4)=(64516)StoreR0,@R3//R3内容为存放临时变量T2值的地址+&T1&1&T2上述四元式的地址表示+645126502464516C1=64512/256=252//T1D1=64512%256=0C2=65024/256=254//常数1D2=65024%256=0C3=64516/256=252//T2D3=64516%256=411例2:(=,ARG1,0,RESULT)其中ARG1是常数地址。解:LoadR3,D1//R3←8LoadR0,C1[R3]//R0←(252*256+8)=(64520)LoadR3,D3//R3←255LoadR3,C3[R3]//R3←(253*256+255)=(65023)StoreR0,@R3//R3的内容为存放变量a值的地址㈡单个四元式的翻译四元式的翻译关键是确定地址,约定如下:指令的第一地址使用R0。指令的第二地址使用R3(兼作变址寄存器)。ARG1、ARG2为变量地址或常数地址,RESULT一定是变量地址。C1=ARG1/256、D1=ARG1%256。C2=ARG2/256、D2=ARG2%256。C3=RESULT/256、D3=RESULT%256。注:C1、C2、C3表示页码,D1、D2、D3表示页内位移。=&T30&a上述四元式的地址表示=64520065023C1=64520/256=252D1=64520%256=8C3=65023/256=253D3=65023%256=25512㈢对照表一条四元式代码通常译成若干条汇编语句,为了便于转移四元式的翻译,应建立一张对照表,记录一个四元式所对应的汇编语句的个数以及汇编语句的编号。对照表结构如下:四元式编号汇编语句条数汇编语句编号181269157.3一个简单目标代码生成器不考虑充分利用寄存器,仅仅使用R0和R3。指令的第一地址使用R0,指令的第二地址使用R3(兼作变址寄存器)。算法描述详见下一页。130.procedureGenCode(op,arg1,arg2,result)//一个简单目标代码生成器1.c1←arg1/256:d1←arg1%256;2.c2←arg2/256:d2←arg2%256;3.c3←result/256:d3←result%256;4.comment:R0←(ARG1)5.outputLoadR3,:outputd1:output换行6.outputLoadR0,:outputc1:output[R3]:output换行7.ifc1=252orc1=253then//ARG1是符号表或临时变量表的入口8.outputLoadR0,@R0:output换行9.endif//ARG1是常数表入口无需上述指令10.comment:R0←运算结果处理加法运算(ARG2≠0)处理一元正运算(ARG2=0)处理减法运算(ARG2≠0)//详见下一页处理一元负运算(ARG2=0)//详见下一页赋值运算(无需任何处理)11.comment:RESULT←(R0)12.outputLoadR3,:outputd3:output换行13.outputLoadR3,:outputc3:output[R3]:output换行14.outputstoreR0,@R3:output换行15.endprocedure14//处理减法运算(ARG2≠0)comment:R0←运算结果ifop=-andarg2≠0thenoutputLoadR3,:outputd2:output换行ifc2=252orc2=253then//ARG2是符号表或临时变量表的入口outputLoadR3,:outputc2:output[R3]:output换行outputSubR0,@R3:output换行else//ARG2是常数表地址outputSubR0,:outputc2:output[R3]endl;endifendif//处理一元负运算(ARG2=0)ifop=-andarg2=0then//-ARG1=0-ARG1outputLoadR3,R0:output换行//将ARG1送R3outputLoadR0,0:output换行//将0送R0outputSubR0,R3:output换行//R0-R3送R0endif15㈡实例设源程序为:a=2+(+b+1),它的四元式代码为+&b0&T1+&T1&1&T2+&2&T2&T3=&T30&a假设整常
本文标题:学习 目标代码生成
链接地址:https://www.777doc.com/doc-3299749 .html