作者:不详 来源:互联网 酷勤网收集 2007-11-22
二、汇编语言常用子程序
1、拆字与拼字:
【例1】将 GR0 中的四位 BCD 码从高到低依次存放到 GR2 所指的四个内存单元中。
| START | |||
| LEA | GR3,4 | ;循环计数器 | |
| L1 | ST | GR0,REG | ;保护其余几位 BCD 码 |
| AND | GR0,C000F | ;屏蔽高 3 位,留下最低 1 位 BCD 码 | |
| ST | GR0,3,GR2 | ;将此位 BCD 码存放到 GR2 所指第四个内存单元 | |
| LD | GR0,REG | ;恢复其余几位 BCD 码 | |
| SRL | GR0,4 | ;将已处理过的此位 BCD 码移出 | |
| LEA | GR2.-1,GR2 | ;地址指针减 1 | |
| LEA | GR3,-1,GR3 | ;循环计数器减 1 | |
| JNZ | L1 | ;未处理完,继续 | |
| RET | |||
| C000F | DC | #000F | ;十六进制常数,屏蔽屏蔽高 3 位 BCD 码用 |
| REG | DS | 1 | ;暂存单元 |
| END |
【例2】将存放在 GR2 所指的四个内存单元中的四位 BCD 码依从高到低顺序压缩到 GR0 中 。
| START | |||
| LEA | GR0,0 | ;GR0 清 0 | |
| LEA | GR3,4 | ;循环计数器 | |
| L1 | SLL | GR0,4 | ;将已处理过的 BCD 码移到高位 |
| LD | GR1,0,GR2 | ;GR1 用作临时工作寄存器 | |
| AND | GR1,C000F | ;屏蔽高 12 位 | |
| ST | GR1,0,GR2 | ;对内存单元中的 BCD 码预处理 | |
| ADD | GR0,0,GR2 | ;将已处理过的此位 BCD 码加到 GR0 低位 | |
| LEA | GR2.1,GR2 | ;地址指针指向下一位 BCD 码 | |
| LEA | GR3,-1,GR3 | ;循环计数器减 1 | |
| JNZ | L1 | ;未处理完,继续 | |
| RET | |||
| C000F | DC | #000F | ;十六进制常数,屏蔽高 12 位二进制数 |
| END |
2、数字与 ASCII 码之间的相互转换:
十进制数字 0~9 的 ASCII 码是 30H~39H ,所以只要将十进制数(BCD 码)加 30H 就是对应的 ASCII 码。
十六进制数转换成 ASCII 码可分成两段, 0~9 的 ASCII 码是 30H~39H ,即加 30H ;A~F 的ASCII 码是 41H~45H ,即加 37 H。
【例1】将 GR0 中的四位 BCD 码化成 ASCII 码从高到低依次存放到字符串变量 STR 中。
| START | |||
| LEA | GR2,3 | ;相对于 STR 首址的地址指针 | |
| LEA | GR3,4 | ;循环计数器 | |
| L1 | ST | GR0,REG | ;保护其余几位 BCD 码 |
| AND | GR0,C000F | ;屏蔽高 3 位,留下最低 1 位 BCD 码 | |
| ADD | GR0,C30 | ;转换成 ASCII 码 | |
| ST | GR0,STR,GR2 | ;将 ASCII 码存放到 GR2 所指第四个内存单元 | |
| LD | GR0,REG | ;恢复其余几位 BCD 码 | |
| SRL | GR0,4 | ;将已处理过的此位 BCD 码移出 | |
| LEA | GR2.-1,GR2 | ;地址指针减 1 | |
| LEA | GR3,-1,GR3 | ;循环计数器减 1 | |
| JNZ | L1 | ;未处理完,继续 | |
| RET | |||
| C000F | DC | #000F | ;十六进制常数,屏蔽高 3 位 BCD 码用 |
| C30 | DC | #30 | ;十六进制常数 30 |
| STR | DS | 4 | |
| REG | DS | 1 | ;暂存单元 |
| END |
【例2】将 GR0 中的 16 位二进制数化成四位十六进制数 ASCII 码从高到低依次存放到字符串变量 STR 中。
| START | |||
| LEA | GR2,3 | ;相对于 STR 首址的地址指针 | |
| LEA | GR3,4 | ;循环计数器 | |
| L1 | ST | GR0,REG | ;保护其余几位二进制数 |
| AND | GR0,C000F | ;屏蔽高 12 位,留下最低 4 位二进制数 | |
| CPL | GR0,C0A | ;< 10 否? | |
| JMI | L2 | ;< 10 跳过加 7 ,只加 30H | |
| ADD | GR0,C7 | ;≥ 10,加 30H 前先加上 7 | |
| L2 | ADD | GR0,C30 | ;加上 30H |
| ST | GR0,STR,GR2 | ;将 ASCII 码存放到 GR2 所指第四个内存单元 | |
| LD | GR0,REG | ;恢复其余几位二进制数 | |
| SRL | GR0,4 | ;将已处理过的此 4 位二进制数移出 | |
| LEA | GR2.-1,GR2 | ;地址指针减 1 | |
| LEA | GR3,-1,GR3 | ;循环计数器减 1 | |
| JNZ | L1 | ;未处理完,继续 | |
| RET | |||
| C000F | DC | #000F | ;十六进制常数,屏蔽屏蔽高 12 位二进制数 |
| C30 | DC | #30 | ;十六进制常数 30 |
| C0A | DC | #0A | ;十六进制常数 0A |
| C7 | DC | 7 | ;常数 7 |
| STR | DS | 4 | |
| REG | DS | 1 | ;暂存单元 |
| END |
【例3】将字符串 STR 中的四位十六进制数的 ASCII 码化成 16 位二进制数放到 GR0 中 。
| START | |||
| LEA | GR0,0 | ;GR0 清 0 | |
| LEA | GR2,0 | ;相对于 STR 首址的地址指针 | |
| LEA | GR3,4 | ;循环计数器 | |
| L1 | SLL | GR0,4 | ;将已处理过的十六进制数移到高位 |
| LD | GR1,STR,GR2 | ;GR1 用作临时工作寄存器 | |
| AND | GR1,C00FF | ;屏蔽高 8 位 | |
| SUB | GR0,C30 | ;减去30H | |
| CPL | GR0,C0A | ;< 10 否? | |
| JMI | L2 | ;< 10 ,完成转换 | |
| SUB | GR0,C7 | ;≥ 10,再减去 7 | |
| L2 | ST | GR1,STR,GR2 | ;将 STR 中的 ASCII 码转换成十六进制数 |
| ADD | GR0,STR,GR2 | ;将此位十六进制数加到 GR0 低位 | |
| LEA | GR2.1,GR2 | ;地址指针指向下一位 ASCII 码 | |
| LEA | GR3,-1,GR3 | ;循环计数器减 1 | |
| JNZ | L1 | ;未处理完,继续 | |
| RET | |||
| C00FF | DC | #00FF | ;十六进制常数,屏蔽高 8 位用 |
| C30 | DC | #30 | ;十六进制常数 30 |
| C0A | DC | #0A | ;十六进制常数 0A |
| C7 | DC | 7 | ;常数 7 |
| STR | DS | 4 | |
| END |
3、利用加减法及移位指令做乘法:
1)左移指令可将操作数乘 2 的整数次方(2、4、8、16);右移指令可将操作数除以 2 的整数次方。
若操作数是无符号数,用逻辑移位指令;若操作数是有符号数,用算术移位指令。
【例1】将 GR0 中的二进制数乘以 8。
| SLL | GR0,3 |
【例2】将 GR0 中的带符号二进制数除以 4。
| SRA | GR0,2 |
2)将移位指令和加减法结合起来可完成乘数不是 2 的整数次方的乘法运算。
【例1】将 GR0 中的二进制数乘以 10。
| START | ||
| SLL | GR0,1 | |
| ST | GR0,REG | |
| SLL | GR0,2 | |
| ADD | GR0,REG | |
| RET | ||
| REG | DS | 1 |
| END |
【例2】将 GR0 中的二进制数乘以 7。
| START | ||
| ST | GR0,REG | |
| SLL | GR0,3 | |
| SUB | GR0,REG | |
| RET | ||
| REG | DS | 1 |
| END |
4、二进制数与十进制数的转换
1)二化十:
将二进制数转换为十进制数的一种常用算法是将被转换的二进制数依次被 10i( 对 16 位二进制数,i为 4、3、2、1、0)除,所得的商即为该十进制数位的值,其余数再被下一个 10i 除。一般用减法代替除法,即一边减 10i,一边计数器加 1,直到不够减再进行下一位 10i-1。以求得十进制数的各位数。
例如:一个相当于十进制数 34635 的二进制数,可先用 10000 去减,可减 3 次,得万位数是 3;再用 1000 去减,得千位数是 4;……
【例1】将 GR0 中的二进制数转换为十进制数的ASCII 码放入字符串 STR 中。
| START | |||
| LEA | GR1,0 | ;减数表及字符串指针 | |
| LEA | GR2,5 | ;循环计数器 | |
| L1 | LEA | GR3,48 | ;该十进制位的数码预置 0 的 ASCII 码 |
| L2 | LEA | GR3,1,GR3 | ;数码位的 ASCII 码加 1 |
| SUB | GR0,SNO,GR1 | ;操作数减去 10i | |
| JPZ | L2 | ;够减,继续 | |
| ADD | GR0,SNO,GR1 | ;不够减,操作数及数码位的 ASCII 码恢复 | |
| LEA | GR3,-1,GR3 | ||
| ST | GR3,STR,GR1 | ;转换好的该位 ASCII 码存入结果字符串 | |
| LEA | GR1,1,GR1 | ;地址指针加 1 | |
| LEA | GR2,-1,GR2 | ;循环计数器减 1 | |
| JNZ | L1 | ;未结束,继续下一位 | |
| RET | |||
| SNO | DC | 10000 | |
| DC | 1000 | ||
| DC | 100 | ||
| DC | 10 | ||
| DC | 1 | ||
| STR | DS | 5 | ;转换结果字符串 |
| END |
1)十化二:
将十进制数转换为二进制数的算法基础是下面公式:
N = (Dn-1*10n-1+Dn-2*10n-2+……+D1*101+D0*100
= ((…((Dn-1*10+Dn-2)*10+……+D1)*10+D0)*10
可以用循环程序实现此公式,*10 可用移位及加法指令完成。
【例2】将存放在字符串 STR 中的五位十进制数(<65536)的 ASCII 码转换成二进制数放到 GR0 中 。
| START | |||
| LEA | GR0,0 | ;转换结果寄存器清 0 | |
| LEA | GR2,5 | ;循环计数器 | |
| LEA | GR1,0 | ;地址指针(偏移量) | |
| L1 | SLL | GR0,1 | ;转换结果*10,先乘以 2 |
| ST | GR0,REG | ;暂存 2*X | |
| SLL | GR0,2 | ;2*X*4=8*X | |
| ADD | GR0,REG | ;8*X + 2*X | |
| LD | GR3,STR,GR1 | ;取一位 ASCII 码 | |
| AND | GR3,C000F | ;将 ASCII 码变成 BCD 码 | |
| ST | GR3,REG | ;结果暂存 | |
| ADD | GR0,REG | ;将新的一位 BCD 码加到转换结果中 | |
| LEA | GR1,1,GR1 | ;地址指针加 1 | |
| LEA | GR2,-1,GR2 | ;循环计数器减 1 | |
| JNZ | L1 | ;未结束,继续下一位 | |
| RET | |||
| C000F | DC | #000F | ;十六进制常数,屏蔽高 12 位二进制数 |
| STR | DC | '35475' | |
| REG | DS | 1 | ;暂存单元 |
| END |
5、求累加和
【例1】将变量 NUMBER 中的 5 个二进制数累加后放入变量 SUM 中。
| START | |||
| LEA | GR2,NUMBER | ;地址指针 | |
| LEA | GR3,5 | ;循环计数器 | |
| LEA | GR0,0 | ;累加和清 0 | |
| L1 | ADD | GR0,0,GR2 | ;累加 |
| LEA | GR2,1,GR2 | ;地址指针指向下一个二进制数 | |
| LEA | GR3,-1,GR3 | ;计数器减 1 | |
| JNZ | L1 | ;未完,继续 | |
| ST | GR0,SUM | ;累加结束,累加和送入 SUM 单元 | |
| RET | |||
| NUMBER | DS | 5 | |
| SUM | DS | 1 | |
| END |

