目录 上一页 下一页 下一章

-84- PC机汇编语言实战精解



continue:





change
code

sub
mov

inc
loop

pop
ret
endp
ends
end
al,20h
[bx],al

bx
chloop

bp
2


main
;将小写字母转换成大写
;将大写字母重新存入字符串

;字符串指针加1
;处理下一个字符

;恢复BP寄存器的原值
;返回主过程,并清空堆栈



  这个程序演示了如何将小写字母转换为大写字母。在主过程中使用了"PUSH DX"指令将DX寄存器中存储的字符串首地址压入堆栈,然后调用CHANGE子过程。那么CHANGE子过程又是如何得到字符串地址的呢?
  首先可以肯定地说直接用"POP"指令不可能从堆栈中取得正确的字符串首地址,这是因为执行"CALL"指令时堆栈中存入了主过程的返回地址。习惯上我们常用"基指针寄存器" --BP来取得数据。
  BP(BASS POINT)寄存器是一个十六位寄存器,它和BX寄存器一样可用于完成间接寻址,不过BP寄存器无法分成两个八位寄存器来使,而且它和BX寄存器也不完全一样。当我们使用BX做间接寻址时,如果不指定段寄存器,则CPU将默认DS寄存器的值为段地址,而使用BP做此工作时,CPU会默认SS的值为段地址,即BP寄存器常用于在堆栈中取得数据时应用。不难想象BP寄存器为我们灵活处理堆栈中的数据提供了便利,这使我们可以不必顾及堆栈数据"后入先出"的规矩,也不必冒险修改SP寄存器。
  需要说明的是BP也可以做其它的工作,比如暂存数据,或在其它段中完成间接寻址,只需注意明确给出段寄存器即可。一般来讲BP寄存器更多地用于取得参数,特别是当我们用汇编语言为一些高级语言编制子模块的时候,这几乎是唯一的方法。因为高级语言在调用子过程时几乎都用堆栈传递数据。
  子过程中的"RET"指令有些不同寻常,它带了一个立即数。由于我们在调用子过程之前将一个数据压入了堆栈,显然子过程返回后这个数已经没有用了,所以我们要调整堆栈指针寄存器SP的值,以恢复堆栈的原始状态。
  采用带常数的RET指令是个比较简单的方法,CPU在执行这样的RET指令时会在返回主过程后自动地将SP寄存器减掉这个常数值,堆栈中的参数也就算自动出栈了。不难想到这个常数在数值上应该等于"参数个数×2"。
  下面是用DEBUG根踪这个程序的过程,请注意观察BP寄存器的应用和堆栈的变化:
-g=0 c[Enter]
welcome to pc world← 程序显示出的字符串
AX=0924BX=0000CX=004EDX=0000SP=0000BP=0000SI=0000DI=0000
DS=1031ES=1021SS=1031CS=1033IP=000C NV UP EI PL NZ NA PO NC
1033:000C52PUSH DX

Copyright © 2004-2015 Reanimator www.cookmoon.org

目录 上一页 下一页 下一章