TEC-2008教学计算机完整知识汇总

本文为课堂学习笔记整理,具体指令行为以实验讲义和上机验证为准。

一、基础概念

1.1 标志位(C/Z/V/S)

标志位用于记录运算结果的状态,供条件转移指令判断使用。

标志位定义

标志位全称含义说明
CCarry 进位- 加法:最高位产生进位,C=1;无进位,C=0
- 减法:最高位产生借位,C=1;无借位,C=0
ZZero 零- 运算结果为 0,Z=1
- 运算结果不为 0,Z=0
VoVerflow 溢出- 有符号数运算结果溢出,V=1
- 有符号数运算结果不溢出,V=0
SSign 符号- 运算结果为正数(最高位为0),S=0
- 运算结果为负数(最高位为1),S=1

标志位示例:二进制加法

text
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(结果被解释为负数)

进位 (C) 和溢出 (V) 的区别

进位是无符号数运算的溢出,溢出是有符号数运算的溢出,二者相互独立:

  1. 示例 1:无进位无溢出
    text
    0011  (3)
    + 0011  (3)
    -------
      0110  (6) 正确
    
    • 无进位,C=0;无溢出,V=0
  2. 示例 2:有进位无溢出
    text
    1111  (-1)
    + 0111  (7)
    -------
     1 0110 (6) 正确
     ---
     进位
    
    • 有进位,C=1;不产生溢出,V=0
  3. 示例 3:有进位有溢出
    text
    1100  (-4)
    + 1000  (-8)
    -------
     1 0100 (截断后为+4,实际结果为-12) 溢出
     --
     进位
    
    • 有进位,C=1;产生溢出:V=1(负数 + 负数 = 正数,违反有符号数运算规则)

1.2 指令格式与寻址方式

TEC-2008 是 16 位教学计算机,支持单字和双字指令。

指令格式结构

8位操作码 4位目的寄存器 DR | 4位源寄存器 SR
8位 I/O 端口地址
8位相对转移指令偏移量
立即数 / 直接地址 / 变址偏移量(双字指令的第二个字)

说明

  • 单字指令:16 位,最高 8 位为操作码;最低 8 位分两种用法:
    1. 运算指令:拆分为 4 位目的寄存器 + 4 位源寄存器
    2. IO/转移指令:作为完整 8 位端口地址或转移偏移量
  • 双字指令:32 位,第二个字用于存放 16 位立即数、直接地址或变址偏移量。

支持的寻址方式

  • 寄存器寻址
  • 寄存器间接寻址([寄存器],以寄存器值为内存地址)
  • 立即数寻址
  • 直接地址寻址
  • 变址寻址
  • 相对寻址
  • 堆栈寻址
  • IO 端口地址

二、完整指令系统

2.1 指令分类

TEC-2008 共支持 29 条基本指令,分为 6 大类:

  1. 数据移动指令 4 条MVRRMVRDLDRRSTRR
  2. 堆栈操作指令 4 条PUSHPOPPSHFPOPF
  3. 输入输出指令 2 条INOUT
  4. 算术逻辑运算指令 11 条ADDSUBANDXORTESTCMPORDECINCSHLSHR
  5. 转移指令 6 条JMPAJRJRCJRNCJRZJRNZ
  6. 子程序调用与返回指令 2 条CALARET

2.2 指令命名规则

缩写全称说明
MVMOVE
LDLOAD
STSTORE
SHSHIFT
JMPJUMP
CALCALL
RETRETURN
JRJUMP RELATIVE
RREGISTER
DDATA
AADDRESS
FFLAGS

2.3 A 组指令

A 组指令为单字运算与相对转移指令,8 位操作码范围000xxxxx0100xxxx:CZVS 列中,* 表示影响该标志位,. 表示不影响标志位,顺序为 C、Z、V、S。

指令格式汇编语句操作数个数CZVS功能说明
00000000 DR SRADD DR, SR2****DR ← DR + SR
00000001 DR SRSUB DR, SR2****DR ← DR - SR
00000010 DR SRAND DR, SR2.*..DR ← DR and SR
00000011 DR SRCMP DR, SR2****DR - SR(不存结果,仅更新标志位)
00000100 DR SRXOR DR, SR2.*..DR ← DR xor SR
00000101 DR SRTEST DR, SR2****DR and SR(不存结果,仅更新标志位)
00000110 DR SROR DR, SR2.*..DR ← DR or SR
00000111 DR SRMVRR DR, SR2....DR ← SR
00001000 DR0000DEC DR1****DR ← DR - 1
00001001 DR0000INC DR1****DR ← DR + 1
00001010 DR0000SHL DR1*...DR, C ← DR * 2(逻辑左移,最高位移入C)
00001011 DR0000SHR DR1*...DR, C ← DR / 2(逻辑右移,最低位移入C)
01000001 OFFSETJR ADR1....无条件相对跳转到 ADR
01000100 OFFSETJRC ADR1....C=1时相对跳转到 ADR
01000101 OFFSETJRNC ADR1....C=0时相对跳转到 ADR
01000110 OFFSETJRZ ADR1....Z=1时相对跳转到 ADR
01000111 OFFSETJRNZ ADR1....Z=0时相对跳转到 ADR

2.4 B/D 组指令

B/D 组指令为内存操作、IO、堆栈、子程序等指令,8 位操作码范围1000xxxx(B组)或 1100xxxx(D组)。 :CZVS 列中,* 表示影响该标志位,. 表示不影响标志位,顺序为 C、Z、V、S。

指令格式汇编语句操作数个数CZVS功能说明
10000000 00000000 ADR(16 位)JMPA ADR1....无条件绝对跳转到 ADR
10000001 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 的子程序

三、汇编程序设计示例

3.1 例 1:输出单个字符 '6'

功能:在屏幕上输出显示一个字符 '6'。

asm
A 2000        ; 地址从16进制的2000开始(内存RAM区的起始地址)
2000: MVRD R0, 36 ; 把字符'6'的ASCII码送入R0
2002: OUT  80     ; 输出显示字符'6',80为串口数据端口地址
2003: RET         ; 每个用户程序都必须用RET指令结束
2004:              ; 按回车键即结束源程序的输入过程

3.2 例 2:计算 1 到 10 的累加和

功能:计算 1 到 10 的累加和,运行后用 R 命令查看 R1 中的结果。

asm
A 2060
MVRD R1, 0000  ; 置累加和的初值为0
MVRD R2, 000A  ; 最大的加数(10)
SUB  R3, R3    ; 预置参加累加的数为0
(2065) INC  R3 ; 得到下一个参加累加的数
ADD  R1, R3    ; 累加计算
CMP  R3, R2    ; 判断是否累加完
JRNZ 2065      ; 未完,开始下一轮累加
RET

3.3 例 3:循环输出 ASCII 可打印字符

功能:在显示器屏幕上循环显示 95 个(包括空格字符)可打印字符。

程序代码

asm
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结束

运行结果

text
>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

ASCII 码字符集

L\H000001010011100101110111
0000NULDLESP0@P`p
0001SOHDC1!1AQAq
0010STXDC2"2BRbr
0011ETXDC3#3CScs
0100EOTDC4$4DTDt
0101ENQNAK%5EUeU
0110ACKSYN&6FVfv
0111BELETB'7GWGw
1000BSCAN(8HXhx
1001HTEM)9IYiy
1010LFSUB*:JZjz
1011VTESC+;K[k{
1100FFFS,<L|l|
1101CRGS-=M]m}
1110SORS.>N^n~
1111SIUS/?O_oDEL

3.4 例 4:数字字符输入过滤

功能:从键盘上键入多个属于 '0' 到 '9' 的数字符并在屏幕上显示,遇非数字符结束程序。

asm
A 2040
IN   81  ; 读串口状态端口,bit1=1表示有键盘输入
SHR  R0  ; 第一次右移,bit0移入C
SHR  R0  ; 第二次右移,bit1移入C
JRNC 2040  ; 无输入则循环检测(C=0时跳转)
(2044) IN   80  ; 把输入字符读到R0低位字节
MVRD R1, 00FF
AND  R0, R1  ; 将R0的高位字节清0
MVRD R2, 0030   ; '0'的ASCII码
MVRD R3, 0039   ; '9'的ASCII码
CMP  R0, R2  ; 判输入字符是否小于'0'
JRNC 2053  ; 小于'0',跳转到程序结束处
CMP  R3, R0  ; 判输入字符是否大于'9'
JRNC 2053  ; 大于'9',跳转到程序结束处
OUT  80  ; 输出刚输入的数字符
JMPA 2044  ; 转去等待下一个字符输入
(2053) RET

注意:以上代码结构需对照实验讲义核实,(2044) 标签之前的指令地址在笔记中未完整记录。 说明

  • CMP 实际执行减法(不存结果)。无符号比较时,R0 < R2 发生借位,C=0;否则 C=1

3.5 例 5:内存读写与大小写转换

功能:读出指定内存中的大写字母字符,将其显示到屏幕上,转换为小写字母后再写回存储器的原存储单元。 操作步骤:用 E 命令送入 6 个字符 'A'~'F' 到内存 20F0 开始的存储区域中,运行后用 D 命令查看。

主程序

asm
A 2080
MVRD  R3,  0006  ; 指定被读数据的个数
MVRD  R2,  20F0  ; 指定被读、写数据内存区首地址
(2084) LDRR  R0,  [R2]  ; 寄存器间接寻址,读内存字符到R0
CALA  2100  ; 调用子程序,入口地址为2100
DEC   R3  ; 剩余字符数减1
JRZ   208B  ; 个数为0则结束程序
INC   R2  ; 内存地址自增
JR    2084  ; 循环处理下一个字符
(208B) RET

子程序

asm
A 2100  ; 子程序从2100单元开始
OUT   80  ; 输出R0中的字符
MVRD  R1, 0020  ; 大写转小写的偏移量
ADD   R0, R1  ; 转换为小写字母
STRR  [R2], R0  ; 写回原内存单元
(2105) IN    81  ; 查询串口输出状态
SHR   R0
JRNC  2105  ; 输出未完成则等待
RET  ; 子程序返回

3.6 例 6:子程序调用:大小写转换

功能:主程序完成从键盘读入字符并显示,调用子程序将大写字母转为小写并再次显示。

主程序

asm
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

子程序

asm
2050: MVRD R1,20  ; 大写转小写偏移量
2052: ADD  R0,R1  ; 转换字符编码
2053: OUT  80  ; 显示小写字符
2054: RET  ; 子程序返回

运行结果

text
>G 2040
AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz

说明:程序无输入判断逻辑,会持续运行。


3.7 例 7:批量内存读写测试

功能:将 A~F 写入内存 2240 开始的区域,并显示出来。

程序录入(错误版本)

asm
>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

运行前内存

text
>D 2240
2240 0000 0000 0000 0000 0000 0000 0000 0000

运行结果

text
>G 2220
ABCDEF

运行后内存

text
>D 2240
2240 0041 0042 0043 0044 0045 0046 0000 0000

3.8 输入输出轮询机制

1. 输出完成等待循环

串口状态定义:81端口bit0=1表示输出完成。

asm
(2028) IN   81  ; 读取串口输出状态
SHR  R0  ; bit0移入进位标志C
JRNC 2028  ; C=0表示未完成,循环等待

测试建议:去掉这三行后,字符可能输出不完整或乱码。

2. 键盘输入检测循环

串口状态定义:81端口bit1=1表示有键盘输入。

asm
(2044) IN  81  ; 读取键盘输入状态
SHR R0  ; 第一次右移
SHR R0  ; 第二次右移,bit1移入C
JRNC 2044  ; C=0表示无输入,循环检测

测试建议:去掉这4行后,程序会直接读取旧数据,无法正常响应按键。

3. PUSH/POP 保护寄存器的作用

OUT 80 输出后需轮询 IN 81,该指令会覆盖R0中的字符数据,因此用堆栈保存恢复:

asm
PUSH R0  ; 保存待显示的字符
IN  81   ; 读取状态,覆盖R0
SHR R0
JRNC 2028
POP R0   ; 恢复原字符

四、程序调试与问题排查

4.1 常见错误与修正

错误示例:跳转指令写错

批量内存读写程序中,将JRNZ写成JRNC,导致循环只执行一次。

错误版本反汇编

asm
>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不成立,不跳转。

修正方法

text
>A 222F
222F: JRNZ 2226

4.2 其他常见错误

  1. STRR 指令遗漏括号:寄存器间接寻址必须加[],错误STRR R2, R1→正确STRR [R2], R1
  2. 相对跳转地址越界:JR类指令偏移量为8位,超出范围需用JMPA绝对跳转

五、常用命令说明

  • A 地址:从指定地址开始汇编输入程序
  • U 地址:反汇编指定地址开始的指令
  • D 地址:查看指定地址开始的内存内容
  • E 地址:修改指定地址开始的内存内容
  • G 地址:从指定地址开始运行程序
  • R:查看当前寄存器的状态
微信
支付宝

感谢您的支持 ♥️

新故事即将发生
如何使用 ollama 和 open-webui 搭建自己的本地 AI 助手

评论区

评论加载中...