TEC-2008教学计算机完整知识汇总 | 敖苛记
标志位用于记录运算结果的状态,供条件转移指令判断使用。
- 减法:最高位产生借位,C=0;无借位,C=1ZZero 零- 运算结果为 0,Z=1
- 运算结果不为 0,Z=0VoVerflow 溢出- 有符号数运算结果溢出,V=1
- 有符号数运算结果不溢出,V=0SSign 符号- 运算结果为正数(最高位为0),S=0
- 运算结果为负数(最高位为1),S=1
0101 (二进制数1) + 0011 (二进制数2) ------- 1000 (二进制和)
- 进位标志位(C):无进位产生,C=0
- 溢出标志位(V):0101(+5)与 0011(+3)均为正数,结果 1000 符号位为 1(负数),发生有符号数溢出,V=1(4 位有符号数范围为 −8~+7,5+3=8 超出上界)
- 零标志位(Z):结果不为 0,Z=0
- 符号标志位(S):结果 1000 符号位为 1,S=1(结果被解释为负数)
进位是无符号数运算的溢出,溢出是有符号数运算的溢出,二者相互独立:
- 示例 1:无进位无溢出
text 0011 (3) + 0011 (3) ------- 0110 (6) 正确
- 无进位,
C=0;无溢出,V=0
- 无进位,
- 示例 2:有进位无溢出
text 1111 (-1) + 0111 (7) ------- 1 0110 (6) 正确 --- 进位
- 有进位,
C=1;不产生溢出,V=0
- 有进位,
- 示例 3:有进位有溢出
text 1100 (-4) + 1000 (-8) ------- 1 0100 (截断后为+4,实际结果为-12) 溢出 -- 进位
- 有进位,
C=1;产生溢出:V=1(负数 + 负数 = 正数,违反有符号数运算规则)
- 有进位,
TEC-2008 是 16 位教学计算机,支持单字和双字指令。
- 单字指令:16 位,最高 8 位为操作码;最低 8 位分两种用法:
- 运算指令:拆分为 4 位目的寄存器 + 4 位源寄存器
- IO/转移指令:作为完整 8 位端口地址或转移偏移量
- 双字指令:32 位,第二个字用于存放 16 位立即数、直接地址或变址偏移量。
- 寄存器寻址
- 寄存器间接寻址(
[寄存器],以寄存器值为内存地址) - 立即数寻址
- 直接地址寻址
- 变址寻址
- 相对寻址
- 堆栈寻址
- IO 端口地址
TEC-2008 共支持 29 条基本指令,分为 6 大类:
- 数据移动指令 4 条:
MVRR、MVRD、LDRR、STRR - 堆栈操作指令 4 条:
PUSH、POP、PSHF、POPF - 输入输出指令 2 条:
IN、OUT - 算术逻辑运算指令 11 条:
ADD、SUB、AND、XOR、TEST、CMP、OR、DEC、INC、SHL、SHR - 转移指令 6 条:
JMPA、JR、JRC、JRNC、JRZ、JRNZ - 子程序调用与返回指令 2 条:
CALA、RET
A 组指令为单字运算与相对转移指令,8 位操作码范围:000xxxxx 或 0100xxxx。
注:CZVS 列中,* 表示影响该标志位,. 表示不影响标志位,顺序为 C、Z、V、S。
00000000 DR SRADD DR, SR2****DR ← DR + SR00000001 DR SRSUB DR, SR2****DR ← DR - SR00000010 DR SRAND DR, SR2.*..DR ← DR and SR00000011 DR SRCMP DR, SR2****DR - SR(不存结果,仅更新标志位)00000100 DR SRXOR DR, SR2.*..DR ← DR xor SR00000101 DR SRTEST DR, SR2****DR and SR(不存结果,仅更新标志位)00000110 DR SROR DR, SR2.*..DR ← DR or SR00000111 DR SRMVRR DR, SR2....DR ← SR00001000 DR0000DEC DR1****DR ← DR - 100001001 DR0000INC DR1****DR ← DR + 100001010 DR0000SHL DR1*...DR, C ← DR * 2(逻辑左移,最高位移入C)00001011 DR0000SHR DR1*...DR, C ← DR / 2(逻辑右移,最低位移入C)01000001 OFFSETJR ADR1....无条件相对跳转到 ADR01000100 OFFSETJRC ADR1....C=1时相对跳转到 ADR01000101 OFFSETJRNC ADR1....C=0时相对跳转到 ADR01000110 OFFSETJRZ ADR1....Z=1时相对跳转到 ADR01000111 OFFSETJRNZ ADR1....Z=0时相对跳转到 ADRB/D 组指令为内存操作、IO、堆栈、子程序等指令,8 位操作码范围:1000xxxx(B组)或 1100xxxx(D组)。
注:CZVS 列中,* 表示影响该标志位,. 表示不影响标志位,顺序为 C、Z、V、S。
10000000 00000000 ADR(16 位)JMPA ADR1....无条件绝对跳转到 ADR10000001 DR SRLDRR DR, [SR]2....DR ← [SR](寄存器间接寻址,从内存加载)10000010 I/O PORTIN I/O PORT1....R0 ← [I/O PORT](从端口读入,固定存入R0)10000011 DR SRSTRR [DR], SR2....[DR] ← SR(寄存器间接寻址,写入内存)10000100 00000000PSHF0....标志寄存器FLAG入栈10000101 0000 SRPUSH SR1....寄存器SR的值入栈10000110 I/O PORTOUT I/O PORT1....[I/O PORT] ← R0(向端口输出,固定取自R0)10000111 DR0000POP DR1....DR ← 栈顶出栈数据10001000 DR0000 DATA(16 位)MVRD DR, DATA2....DR ← DATA(加载16位立即数)10001100 00000000POPF0****FLAG ← 栈顶出栈数据(恢复全部标志位)10001111 00000000RET0....子程序返回11001110 00000000 ADR(16 位)CALA ADR1....调用首地址为 ADR 的子程序扩展指令操作码不在基本指令范围内,需通过交叉汇编器的扩展指令表加载后才能使用。
00100000 DR SRADC DR, SR****DR ← DR + SR + C(带进位加)00100001 DR SRSBB DR, SR****DR ← DR - SR - C(带借位减)00101010 DR0000RCL DR*...带进位循环左移,最高位移入C,C移入最低位00101011 DR0000RCR DR*...带进位循环右移,最低位移入C,C移入最高位00101100 DR0000ASR DR*...算术右移,保持符号位不变00101101 DR0000NOT DR....DR ← ~DR(按位取反)01100000 00000000JMPR....无条件寄存器间接跳转(目标地址在 R11:R10)01100100 OFFSETJRS ADR....S=1 时相对跳转01100101 OFFSETJRNS ADR....S=0 时相对跳转01101100 00000000CLC*...清进位标志,C=001101101 00000000STC*...置进位标志,C=101101110 00000000EI....开中断01101111 00000000DI....关中断11100000 00000000CALR....寄存器间接调用子程序(目标地址在 R11:R10)11100100 DR SRLDRA DR, [ADDR]....直接地址加载,DR ← [ADDR]11100100 DR SRLDRX DR, [SR+ADDR]....变址寻址加载,DR ← [SR + ADDR]11100110 DR SRSTRX [SR+ADDR], DR....变址寻址存储,[SR + ADDR] ← DR11100111 DR SRSTRA [ADDR], DR....直接地址存储,[ADDR] ← DR11101111 00000000IRET****中断返回(恢复 PC 和标志位)功能:在屏幕上输出显示一个字符 '6'。
A 2000 ; 地址从16进制的2000开始(内存RAM区的起始地址) 2000: MVRD R0, 36 ; 把字符'6'的ASCII码送入R0 2002: OUT 80 ; 输出显示字符'6',80为串口数据端口地址 2003: RET ; 每个用户程序都必须用RET指令结束 2004: ; 按回车键即结束源程序的输入过程
功能:计算 1 到 10 的累加和,运行后用 R 命令查看 R1 中的结果。
A 2060 2060: MVRD R1, 0000 ; 置累加和的初值为0 2062: MVRD R2, 000A ; 最大的加数(10) 2064: SUB R3, R3 ; 预置参加累加的数为0 2065: INC R3 ; 得到下一个参加累加的数 2066: ADD R1, R3 ; 累加计算 2067: CMP R3, R2 ; 判断是否累加完 2068: JRNZ 2065 ; 未完,开始下一轮累加 2069: RET
功能:在显示器屏幕上循环显示 95 个(包括空格字符)可打印字符。
A 2000 ; 从内存的2000单元开始建立用户的第一个程序 2000: MVRD R1, 7E ; 向寄存器传送直接数,7E是'~'的ASCII码 2002: MVRD R0, 20 ; 20是空格的ASCII码,从空格开始输出 2004: OUT 80 ; 通过串行接口输出R0低位字节内容到显示器屏幕 2005: PUSH R0 ; 保存R0寄存器的内容到堆栈中 2006: IN 81 ; 读串口状态端口,bit0=1表示输出完成 2007: SHR R0 ; R0寄存器的内容右移一位,bit0移入进位标志C 2008: JRNC 2006 ; C≠1则输出未完成,继续查询 2009: POP R0 ; 从堆栈中恢复R0寄存器的原内容 200A: CMP R0, R1 ; 比较两个寄存器的内容,相等则Z=1 200B: JRZ 200E ; Z=1则跳转到程序结束 200C: INC R0 ; R0自增,取下一个字符 200D: JR 2004 ; 无条件跳转继续输出 200E: RET ; 子程序返回指令,教学计算机的用户程序必须用RET结束
>G 2000
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno
pqrstuvwxyz{|}~
R0=007E R1=007E R2=20F5 R3=0000 SP=2780 PC=2200 R6=0000 R7=0000 R8=0000
R9=0000 R10=0000 R11=0000 R12=0000 R13=0000 R14=2612 R15=0000 F=11000000
功能:从键盘上键入多个属于 '0' 到 '9' 的数字符并在屏幕上显示,遇非数字符结束程序。
A 2040 2040: IN 81 ; 读串口状态端口,bit1=1表示有键盘输入 2041: SHR R0 ; 第一次右移,bit0移入C 2042: SHR R0 ; 第二次右移,bit1移入C 2043: JRNC 2040 ; 无输入则循环检测(C=0时跳转) 2044: IN 80 ; 把输入字符读到R0低位字节 2045: MVRD R1, 00FF 2047: AND R0, R1 ; 将R0的高位字节清0 2048: MVRD R2, 0030 ; '0'的ASCII码 204A: MVRD R3, 0039 ; '9'的ASCII码 204C: CMP R0, R2 ; 判输入字符是否小于'0' 204D: JRNC 2053 ; 小于'0',跳转到程序结束处 204E: CMP R3, R0 ; 判输入字符是否大于'9' 204F: JRNC 2053 ; 大于'9',跳转到程序结束处 2050: OUT 80 ; 输出刚输入的数字符 2051: JMPA 2044 ; 转去等待下一个字符输入 2053: RET
说明:
CMP实际执行减法(不存结果)。无符号比较时,R0 < R2发生借位,C=0;否则C=1。
功能:读出指定内存中的大写字母字符,将其显示到屏幕上,转换为小写字母后再写回存储器的原存储单元。
操作步骤:用 E 命令送入 6 个字符 'A'~'F' 到内存 20F0 开始的存储区域中,运行后用 D 命令查看。
A 2080 2080: MVRD R3, 0006 ; 指定被读数据的个数 2082: MVRD R2, 20F0 ; 指定被读、写数据内存区首地址 2084: LDRR R0, [R2] ; 寄存器间接寻址,读内存字符到R0 2085: CALA 2100 ; 调用子程序,入口地址为2100 2087: DEC R3 ; 剩余字符数减1 2088: JRZ 208B ; 个数为0则结束程序 2089: INC R2 ; 内存地址自增 208A: JR 2084 ; 循环处理下一个字符 208B: RET
A 2100 2100: OUT 80 ; 输出R0中的字符 2101: MVRD R1, 0020 ; 大写转小写的偏移量 2103: ADD R0, R1 ; 转换为小写字母 2104: STRR [R2], R0 ; 写回原内存单元 2105: IN 81 ; 查询串口输出状态 2106: SHR R0 2107: JRNC 2105 ; 输出未完成则等待 2108: RET ; 子程序返回
功能:主程序完成从键盘读入字符并显示,调用子程序将大写字母转为小写并再次显示。
A 2040 2040: IN 81 ; 检测键盘输入 2041: SHR R0 2042: SHR R0 2043: JRNC 2040 2044: IN 80 ; 读取输入字符到R0 2045: OUT 80 ; 显示原字符 2046: PUSH R0 ; 保存R0 2047: IN 81 ; 等待输出完成 2048: SHR R0 2049: JRNC 2047 204A: POP R0 ; 恢复R0 204B: CALA 2050 ; 调用转换子程序 204D: JMPA 2040 ; 循环读取 204F: RET
A 2050 2050: MVRD R1, 0020 ; 大写转小写偏移量 2052: ADD R0, R1 ; 转换字符编码 2053: OUT 80 ; 显示小写字符 2054: RET ; 子程序返回
>G 2040 AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz
说明:程序无输入判断逻辑,会持续运行。
功能:将 A~F 写入内存 2240 开始的区域,并显示出来。
>A 2220
2220: MVRD R3, 6
2222: MVRD R2, 223f
2224: MVRD R1, 40
2226: INC R2
2227: INC R1
2228: STRR R2, R1 ; 错误:寄存器间接寻址必须加[]
^Error
2228: STRR [R2], R1 ; 正确写法
2229: LDRR R0, [R2]
222A: OUT 80
222B: IN 81
222C: SHR R0
222D: JRNC 202b ; 错误:相对跳转地址超出范围
^Error
222D: JRNC 222b ; 正确写法
222E: DEC R3
222F: JRNC 2226 ; 错误:应使用JRNZ判断循环
2230: RET
>D 2240 2240 0000 0000 0000 0000 0000 0000 0000 0000
>G 2220 ABCDEF
>D 2240 2240 0041 0042 0043 0044 0045 0046 0000 0000
串口状态定义:81端口bit0=1表示输出完成。
2028: IN 81 ; 读取串口输出状态 2029: SHR R0 ; bit0移入进位标志C 202A: JRNC 2028 ; C=0表示未完成,循环等待
测试建议:去掉这三行后,字符可能输出不完整或乱码。
串口状态定义:81端口bit1=1表示有键盘输入。
2044: IN 81 ; 读取键盘输入状态 2045: SHR R0 ; 第一次右移 2046: SHR R0 ; 第二次右移,bit1移入C 2047: JRNC 2044 ; C=0表示无输入,循环检测
测试建议:去掉这4行后,程序会直接读取旧数据,无法正常响应按键。
OUT 80 输出后需轮询 IN 81,该指令会覆盖R0中的字符数据,因此用堆栈保存恢复:
2005: PUSH R0 ; 保存待显示的字符 2006: IN 81 ; 读取状态,覆盖R0 2007: SHR R0 2008: JRNC 2006 2009: POP R0 ; 恢复原字符
批量内存读写程序中,将JRNZ写成JRNC,导致循环只执行一次。
>U 2220 2220: MVRD R3, 0006 2222: MVRD R2, 223F 2224: MVRD R1, 0040 2226: INC R2 2227: INC R1 2228: STRR [R2], R1 2229: LDRR R0, [R2] 222A: OUT 0080 222B: IN 0081 222C: SHR R0 222D: JRNC 222B 222E: DEC R3 222F: JRNC 2226 ; 错误:应该用JRNZ 2230: RET
DEC R3 后 R3≠0,Z=0;无借位C=1,JRNC判断C=0不成立,不跳转。
>A 222F 222F: JRNZ 2226
- STRR 指令遗漏括号:寄存器间接寻址必须加
[],错误STRR R2, R1→正确STRR [R2], R1 - 相对跳转地址越界:JR类指令偏移量为8位,超出范围需用JMPA绝对跳转
A 地址:从指定地址开始汇编输入程序U 地址:反汇编指定地址开始的指令D 地址:查看指定地址开始的内存内容E 地址:修改指定地址开始的内存内容G 地址:从指定地址开始运行程序T 地址:从指定地址开始单步执行(跟踪进入子程序),每次执行后显示所有寄存器及状态位的值R:查看当前寄存器的状态