今天看王爽老师的《汇编语言》时,很有收获,不论是技术还是思考方式。
任务是将字符串进行大小写转换,但是还暂时不会用分支判断语句(而且这样的效率也不是最高的,有点类似于高级语言了)。
“如果一个问题的解决方法,使我们陷入一种矛盾之中。那么,很可能是我们考虑问题的出发点有了问题,或是说,我们起初运用的规律并不适合。”(强行被王老师灌了一碗鸡汤,爽!)
扯点淡:这两天正好遇到一点事情,使我略微开始怀疑自己,(当然也没那么严重,卓教授可是非常厉害的,承载了太多期许的目光,岂能轻言放弃。不能把世界交给我看不起的人!),所以王老师的这句话使我,换一种思考方式,也许会柳暗花明。
初步想法是,判断字符的ASCII码,如果大于61H,则减20H。但是没有判断语句,所以这条道走不通。
我们应该重新观察,寻找新的规律。可以看出,就ASCII码的二进制形式来看,除第5位(位数从0开始计算)外,大写字母和小写字母的其他各位都一样。大写字母ASCII码的第5位为0,小写字母的第5位为1。这样,我们就有了新的方法,一个字母,不管他原来是大写还是小写,将他的第5位置0,他就必将变为大写字母;将他的第5位置1,他就必将变为小写字母。在这个方法中,我们不需要在处理前判断字母的大小写。
果然,奇技淫巧...
代码如下:
assume cs:code, ds:data

data segment
      db 'BaSiC'
      db 'iNfOrMaTiOn'
data ends

code segment
start:
      mov ax, data
      mov ds, ax  ;设置ds指向data段
      mov bx, 0   ;设置(bx)=0,ds:bx指向'BaSiC'的第一个字母
      mov cx, 5   ;设置循环次数

      s1:
      mov al, [bx]      ;将ASCII码从ds:bx所指向的单元中取出
      and al, 11011111B ;将al中的ASCII码的第5位置为0,变为大写字母
      mov [bx], al      ;将转变后的ASCII码写回原单元
      inc bx      ;(bx)加1,ds:bx指向下一个字母
      loop s1

      mov bx, 5   ;设置(bx)=5,ds:bx指向'iNfOrMaTiOn'的第一个字母
      mov cx, 11  ;设置循环次数,因为'iNfOrMaTiOn'有11个字母

      s2:
      mov al, [bx]
      or al, 00100000B  ;将al中的ASCII码的第5位置为1,变为小写字母
      mov [bx], al
      inc bx
      loop s2

      mov ax, 4c00h
      int 21h
code ends
end start
在以后的操作中,可以从更底层的角度看看能否通过位运算来实现,效率更高,结果更精准。