-----------------------------2021.3.15更新-----------------------------------------
突然想到,其實小寫字母第5位是1,大寫字母第5位是0,也就是意味着相差32,不過前者是因,后者是果。我們習慣了十進制,一眼望去就先望到了果,要是我們是二進制世界,那應該一看就看到了因
-----------------------------2021.3.15更新-----------------------------------------
來源於王爽老師的 匯編語言
. .......... .... ..... .... ...... .. .... ...... ......
問題描述
我們要把字符串里面的小寫字母變成大寫字母,剛開始想着大小寫字母的ASCII碼相差32(20h)那么我們只要把小寫字母的ASCII碼值減32(20h)不久好了,但是,這繞不開一件事,就是判斷一個字母是大寫還是小寫,但我們匯編還沒學到判斷邏輯的實現那么要從新想辦法。
我們應該重新觀察,尋找新的規律。可以看出,就ASCII碼的二進制形式來看,除第5位(位數從0開始計算)外,大寫字母和小寫字母的其他各位都一樣。大寫字母ASCII碼的第5位為0,小寫字母的第5位為1。這樣,我們就有了新的方法,一個字母,不管它原來是大寫還是小寫,將它的第5位置0,它就必將變為大寫字母;將它的第5位置1,它就必將變為小寫字母。在這個方法中,我們不需要在處理前判斷字母的大小寫。比如:
對於“BaSiC”中的“B”,按要求,它已經是大寫字母了,不應進行改變,將它的第5位設為0,它還是大寫字母,因為它的第5位本來就是0。
用什么方法將一個數據中的某一位置0還是置1?當然是用我們剛剛學過的or和and指令。
完整的匯編代碼如下
assume cs:codesg,ds:datasg
datasg segment
db'BaSiC'
db 'iNfOrMaTion'
datasg ends
codesg segment
start:mov ax,datasg
mov ds,ax ;設置ds 指向 datasg段
mov bx,0 ;設置(bx)=0,ds:bx指向'Basic'的第一個字母
mov cx,5 ;設置循環次數5,因為Basic1有5個字母
s:mov al,[bx] ;將ASCII碼從ds:bx所指向的單元中取出
and.al,11011111B ;將a1中的ASCII碼的第5位置為0,變為大寫字母
mov[bx],al ;將轉變后的ASCII碼寫回原單元
inc bx ;(bx)加1,ds:bx指向下一個字母
loop s
mov bx,5 ;設置(bx)=5,ds:bx指向iNfOrMaTion’的第一個字母
mov cx,11 ;設置循環次數11,因為’iNfOrMaTion'有11個字母s0:
s0:mov al,[bx]
or al,00100000B ;將a1中的ASCII碼的第5位置為1,變為小寫字母
mov[bx],al
inc bx
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
由於ASCII碼表中的字符最高位都是0,所以和11011111B
做與運算和 01011111B
做與運算結果都是一樣的,也就是說我們只要和01011111B
(下划線 '_'
)做與運算,就可以實現大寫字母變小寫字母
同理,小寫變大寫也是一樣,我們只要和00100000B
(空格 ' '
)做與運算,就可以實現小寫字母變大寫字母
再引申,也就得出了大變小,小變大的方法 ———— 異或 ,只要第五位反轉就是大變小,小變大,要想反轉,那就和 0 異或,所以就有只要和00100000B
(空格 ' '
)做異或運算,就可以實現大變小,小變大。