[]]
突然想到,小写字母的第 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 指令。
完整的汇编代码如下
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre><code class="prism language-c">assume cs<span class="token punctuation">:</span>codesg<span class="token punctuation">,</span>ds<span class="token punctuation">:</span>datasg
datasg segment
db<span class="token string">'BaSiC'</span>
db <span class="token string">'iNfOrMaTion'</span>
datasg ends
codesg segment
start<span class="token punctuation">:</span>mov ax<span class="token punctuation">,</span>datasg
mov ds<span class="token punctuation">,</span>ax <span class="token punctuation">;</span>设置ds 指向 datasg段
mov bx<span class="token punctuation">,</span><span class="token number">0</span> <span class="token punctuation">;</span>设置(bx)<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span>ds<span class="token punctuation">:</span>bx指向<span class="token string">'Basic'</span>的第一个字母
mov cx<span class="token punctuation">,</span><span class="token number">5</span> <span class="token punctuation">;</span>设置循环次数<span class="token number">5</span><span class="token punctuation">,</span>因为Basic1有<span class="token number">5</span>个字母
s<span class="token punctuation">:</span>mov al<span class="token punctuation">,</span><span class="token punctuation">[</span>bx<span class="token punctuation">]</span> <span class="token punctuation">;</span>将ASCII码从ds<span class="token punctuation">:</span>bx所指向的单元中取出
and<span class="token punctuation">.</span>al<span class="token punctuation">,</span><span class="token number">11011111</span>B <span class="token punctuation">;</span>将a1中的ASCII码的第<span class="token number">5</span>位置为<span class="token number">0</span><span class="token punctuation">,</span>变为大写字母
mov<span class="token punctuation">[</span>bx<span class="token punctuation">]</span><span class="token punctuation">,</span>al <span class="token punctuation">;</span>将转变后的ASCII码写回原单元
inc bx <span class="token punctuation">;</span>(bx)加<span class="token number">1</span><span class="token punctuation">,</span>ds<span class="token punctuation">:</span>bx指向下一个字母
loop s
mov bx<span class="token punctuation">,</span><span class="token number">5</span> <span class="token punctuation">;</span>设置(bx)<span class="token operator">=</span><span class="token number">5</span><span class="token punctuation">,</span>ds<span class="token punctuation">:</span>bx指向iNfOrMaTion’的第一个字母
mov cx<span class="token punctuation">,</span><span class="token number">11</span> <span class="token punctuation">;</span>设置循环次数<span class="token number">11</span><span class="token punctuation">,</span>因为’iNfOrMaTion'有<span class="token number">11</span>个字母s0:
s0<span class="token punctuation">:</span>mov al<span class="token punctuation">,</span><span class="token punctuation">[</span>bx<span class="token punctuation">]</span>
or al<span class="token punctuation">,</span><span class="token number">00100000</span>B <span class="token punctuation">;</span>将a1中的ASCII码的第<span class="token number">5</span>位置为<span class="token number">1</span><span class="token punctuation">,</span>变为小写字母
mov<span class="token punctuation">[</span>bx<span class="token punctuation">]</span><span class="token punctuation">,</span>al
inc bx
loop s0
mov ax<span class="token punctuation">,</span><span class="token number">4</span>c00h
<span class="token keyword">int</span> <span class="token number">21</span>h
codesg ends
end start
</code></pre></p>
ASCII 码表中的字符最高位皆为 0。因此,与某字符做与运算,和与该字符做与运算的结果相同。这意味着,只要与(下划线 '\_')做与运算,就能够将大写字母转变为小写字母。
同理,大写变小写也是如此。我们只要与(空格 ' ')进行与运算,就能够达成大写字母变小写字母的效果。
进一步引申,可以得出大变小、小变大的方法——异或。当第五位反转时,就会实现大变小、小变大。若要进行反转,只需与 0 做异或运算。所以,只要与某个特定的数做异或运算,就能够实现大变小、小变大。
这是具体的实现方式,实现英文字母的大小写互换。可以将所有英文字母都变成小写,也可以将所有英文字母都变成大写,并且是通过位运算来实现的。 |