- 系统分解
1.算法三个定义特性:有限性、确定性、可计算性
2.将一个程序分解成独立的多个小模块(unit),每个小单元可以独立实现和运行特性,叫系统分解。
- 三种结构
1.三种结构是顺序、条件、循环。
- 字符数统计例子
思路:用一个寄存器当指针指向字符串地址,然后一个寄存器存储指针所指的值,一个寄存器存储用户输入值,每一次循环,比对指针所指的字符和输入字符是否一样,一样的+1(到另一个寄存器),然后指针+1,然后判断指针是否是哨兵,如果不是继续循环。
.ORIG X3000
AND R2,R2,#0
LEA R3,STR1
TRAP X23
LOOP1 LDR R1,R3,#0
BRZ LEAVE
NOT R1,R1
ADD R1,R1,#1
ADD R1,R1,R0
BRnp TEMP
ADD R2,R2,#1
TEMP ADD R3,R3,#1
BR LOOP1
LEAVE LD R0,ASCII
ADD R0,R0,R2
TRAP X21
HALT
ASCII .FILL X30
STR1 .STRINGZ "AAAABBBC"
.END
程序解析:
- 寄存器作用:
R2清零,用于统计相同字符个数
R3作为指针,指向字符的地址(LEA)
R1用来存放R3指向的字符(LDR)
R0用来存放用户输入字符(TRAP X23)
R4用来确定是否到尾部,字符串尾部为'X00'- 程序:
1.程序首先判断R1是否为'x00',如果是的话说明到了尾部(这里用到了条件结构的知识)
2.若不是尾部,则判断R1是否与R0相同,若相同则R2++,不同则继续循环(循环结构)
3.最后到达尾部,记得把R2的值加上x30(不是#30!!).因为寄存器的值使用16进制表达的,如果R2等于4,R2实际上是x04,加上x30之后是x34才表达的是十进制的4.
结果:

- 乘法程序(结果在10内)
1.说明一下为什么结果要在10以内,因为我要的是输出字符ASCII,所以只能表示10以内的字符,否则操作难度加大很多。如果是保存在内存里的话则表示的范围会大很多。
2.思路:一个寄存器存储一个因子A,另一个寄存器存储因子B,然后A自加B-1次。比如2*3,2自加2次或3自加1次。
.ORIG X3000
BR START
LOOP LDR R0,R1,#0
BRz EXIT
L2 LDI R3,DSR
BRzp L2
STI R0,DDR
ADD R1,R1,#1
BRnzp LOOP
EXIT RET
START LEA R1,str1
JSR LOOP
TRAP X23
ADD R4,R0,#0
LD R1,ASCII
NOT R1,R1
ADD R1,R1,#1
ADD R4,R4,R1
LEA R1,str2
JSR LOOP
TRAP X23
ADD R5,R0,#0
LD R1,ASCII
NOT R1,R1
ADD R1,R1,#1
ADD R5,R5,R1
ADD R6,R4,#0
LOOP2 ADD R5,R5,#-1
BRnz over
ADD R6,R6,R4
BR LOOP2
over LEA R1,str3
JSR LOOP
ADD R0,R6,#0
LD R1,ASCII
ADD R0,R0,R1
TRAP X21
HALT
str1 .STRINGZ "ENTER A NUMBER A: "
str2 .STRINGZ "ENTER A NUMBER B: "
str3 .STRINGZ "A * B = "
ASCII .FILL #48
DSR .FILL XFE04
DDR .FILL XFE06
.END
程序解析:
- LOOP是一个函数入口,在主程序中JSR调用,注意要在函数最后写RET(这个函数主要是打印字符串,R1用作指针,string存储到R0,字符串结束表示为x0000,然后判断DSR是否忙碌,然后输入到DDR)
- 输入的数字都是字符ASCII,在寄存器里会转换成十六进制(比如你输入3,实际上是x33,十进制为51)所以要先做减法变成十六进制的个位数,然后显示字符的时候再加上去。(ASCII .FILL #48 同上面程序的x30相同)
- 乘法执行部分主要用到循环结构。2*3就是2加三遍(自加2遍2+2+2)。不过要注意循环条件,用好调试debug。

- 求一列数字和
思路:指针,然后设计一个寄存器做total sum,然后循环直到遇到x0000
先做一个hex文件,输入一列数字
4000
000A
000B
000C
000D
000E
000F
0010
0011
0012
0013
0014
程序解析:
- 4000表示起始位置是x4000
- 000A到0014表示的是10~20
- stimulation先加载这个的obj程序,再加载主程序
下面是主程序
.ORIG X3000
AND R1,R1,#0
LD R6,ET
LOOP LDR R5,R6,#0
BRZ EXIT
ADD R1,R5,R1
ADD R6,R6,#1
BR LOOP
EXIT LEA R4,SAVE
STR R1,R4,#0
HALT
ET .FILL X4000
SAVE .BLKW #1
.END
程序解析:
- R6是指向一列数字(况且称为数组吧)的指针,R5存储指针所指的值,R1是和,计算结果保存到SAVE内存里
- 首先要判断R5是不是0(结束条件),如果不是则加到R1里,然后R6指向下一位,循环。
- 程序较简单

1.程序结束后,R1为165(十六进制转为十进制,但是字符是输不出的,所以说如果保存到内存可以表示很大的数,但是输出则比较难)
2.R6地址为X400B,末尾了

save内存存储了R1的值。
6.求一个字中第一个1
求第一个1的位置,从左往右(0-15),若没有则R1=-1. 所以R1先设为15,注意循环中断条件:碰到1或者R1=-1
.ORIG X3000
AND R1,R1,#0
ADD R1,R1,#15
LEA R2,BIT
LDR R3,R2,#0
LD R4,DET
LOOP AND R5,R4,R3
BRnp OVER
ADD R3,R3,R3
ADD R1,R1,#-1
BRn OVER
BR LOOP
OVER HALT
DET .FILL X8000
BIT .BLKW 1
.END
程序解析:
1.R1初始化为15,从右往左检测。
2.一个数自加就是左移
3.与X8000屏蔽码进行AND计算,R5不为0则Over
4.注意当R1=-1时也要退出loop
字右移
思路:字左移就是自加,比如0000…10 左移15次,就变成000…001了(假如15位后到0位,实际上不是这样),所以可以用这个思路来实现右移。不过要分两部分:15位有1和15位为0.
.ORIG X3000
LD R0,NUM
AND R1,R1,#0
ADD R1,R1,#15
LOOP ADD R0,R0,#0
BRN NEG
BRP POS
NEG ADD R0,R0,R0
ADD R0,R0,#1
ADD R1,R1,#-1
BRNZ DONE
BR LOOP
POS ADD R0,R0,R0
ADD R1,R1,#-1
BRNZ DONE
BR LOOP
DONE LD R1,MASK
AND R0,R0,R1
ST R0,NUM
HALT
NUM .FILL X40
MASK .FILL X7FFF
.END
程序解析:
- 任意一个字左移15次等于右移一次,这是核心思想。
- 分正数情况和负数情况,因为15位为1左移,就变成1位为1了
- 最后得到右移一位后的数字存储在R0,
- 最后用屏蔽码将15位清0,因为15位是不可能为1的