前言
点赞再看,养成习惯!
该系列博文基于王爽老师 <汇编语言 第四版> 一书,需要的同学链接自取:
链接:https://pan.baidu.com/s/1NAgD1Z15LtK1BuH92xmICA
提取码:xlzb
另外书中提到的DosBox软件不想去官网下载的小伙伴也可以自取:
链接:https://pan.baidu.com/s/1O6PnLb_hN-WUS2avicNpcw
提取码:xlzb
最后如果还没有计算机基础的同学,建议先补充下计算机相关的基础知识:
从今天的内容开始,我们会逐渐地从理论知识转向实战,希望小伙伴们能够跟上节奏,早日完成汇编语言的学习。
一、编码
1.1 ASCII码
通过之前的学习我们知道,计算机最初的设计是通过二进制进行数据的采集和展示,而之后我们又学习了进制之间的转换,让二进制数可以转换为十进制或十六进制等更符合人类阅读习惯的数字,这样我们就可以录入更多的数据。但是我们知道,人类更擅长的是去理解已经约定的具有器含义的字符。比如当你看到123,你就知道这是一个数值,当你看到ABC你就能知道这是串英文字母,而再进一步,当你看到Book你就知道这是指书本,人类对于这些特殊字符的认识过程其实就是一个信息解码的过程,而再解码前我们就需要拥有一个编码赋予这些特殊字符一些特殊的含义。计算机也是这样的,如果我们想要将特殊的信息存放进计算机中,我们就需要将这些信息进行编码,以约定好的规则放入计算机中,这样在我们需要获取信息的时候就可以通过同样的约定进行解码,让我们理解我们存入的信息是什么。
世界上有很多种编码方案,而对于程序员来说,首先接触的基本都是ASCII编码。这是一种再计算机中常被使用的编码方式。简单的来说,ASCII码就是一套规则,它约定好了用什么样的信息来用数字表示对现实的抽象映射。比如说,如果我们想要让计算机表达字母a,那么我们只需要按照ASCII码表录入61H即可。
这里我们可以做一个简单的测试:
代码:
# 我们编写一个简单的数据录入程序
# 通过DOSBOX观察内存状态
assume cs:code,ds:data
data segment
dw 41H,42H,43H,44H,45H,46H
data ends
code segment
start : mov ax,data
mov ax,4c00H
int 21H
code ends
end start
end
DOSBOX测试:
如果不喜欢看运行步骤的小伙伴,可以直接看结果哈:
这里我们可以观察到,当我们录入41H的时候,DOSBOX对应的按照ASCII表的约定在右侧解析出了大写字母A,同理,当我们录入42H的时候,右侧对应的出现了大写字母B,这意味着当我们按照ASCII码表的约定录入数字的时候,计算机是可以知道我们想要表达的含义的。
这里需要注意的是41H表示的是十六进制数字,其对应的十进制数字是65
1.2 字符与编码
当然如果每次我们在编写代码的时候,还需要参照ASCII码录入数据是很不方便的,于是在编码的基础上,编译器又做了进一步的拓展,我们可以直接在代码中录入字符数据,这时编译器就会按照约定好的码表将字符转换成数据录入内存。比如:
assume cs:code,ds:data
data segment
db 'book'
db 'desk'
data ends
code segment
start : mov ax,data
mov ax,4c00H
int 21H
code ends
end start
end
这里讲一下声明数据时使用的DW和DB的区别:
DW是double word的简写,表示占用两个字大小的空间
DB是double byte的简写,表示占用两个字节的空间
让我们看一下结果:
虽然我们录入的是字符数据book,但是编译器依旧是按照编码规则存入了对应的数字,这也意味着编译器为我们做好了编码的工作。
二、逻辑运算
今天我们还要学两个新的指令:and 和or
2.1 and指令
在汇编逻辑中,and指令表示要求程序按位进行与逻辑运算。
与逻辑是指:
当1与1的时候 其值为1
当1与0的时候 其值为0
当0与0的时候 其值为0
让我们做一个简单的测试:
assume cs:code
code segment
start :
mov al,00001111B
and al,11110000B
mov ax,4c00H
int 21H
code ends
end start
end
测试结果:
2.2 or指令
与and相对的,or指令是指要求数据按位进行或运算。
或逻辑是指:
0 或 0 为 0
0 或 1 为 1
1 或 1 为 1
同样的,我们做个测试:
assume cs:code
code segment
start :
mov al,00001111B
or al,11110000B
mov ax,4c00H
int 21H
code ends
end start
end
运算结果:
三、字母的大小写转换
接下来我们需要思考这样一个问题,我们可不可以编写一个程序,可以通过代码实现字母之间的大小写转换呢?
3.1 通过加减法形式实现
第一步我们需要做的就是观察一下字母的数据结构,尝试看能不能找到某种规律。
小写字母a 在ASCII码表中为97,其二进制码为:
110 0001B
大写字母A 在ASCII码表中为65,其二进制码为:
100 0001B
a:110 0001B
A:100 0001B
我们观察上面的数字,首先我们通过十进制码可以找到的规律是小写字母的码值要比大写字母多32,用十六进制表示则为20H,二进制为10 0000。那是不是说我们只要通过加减20H即可完成大小写的转换呢?让我们来试一试。
assume cs:code ,ds:data
data segment
db 'A'
data ends
code segment
start :
mov ax,data
mov bx,0H
mov ds,ax
mov ax,ds:[bx]
add ax,20H
mov ds:[bx],ax
mov ax,4c00H
int 21H
code ends
end start
end
测试结果
到这里我们已经字母大小写的转换就已经完成了,但是这种方式存在一定的局限。
- 我们没有办法判断当前字母是大写还是小写,没有很灵活的完成动态转换。
3.2 逻辑运算进行字母大小写的转换
我们重新进行观察,尝试寻找新的规律:
小写字母a 在ASCII码表中为97,其二进制码为:
110 0001B
大写字母A 在ASCII码表中为65,其二进制码为:
100 0001B
a:110 0001B
A:100 0001B
小写字母b 在ASCII码表中为98,其二进制码为:
110 0010B
大写字母B 在ASCII码表中为66,其二进制码为:
100 0010B
b:110 0010B
B:100 0010B
我们观察到大写字母与小写字母二进制数字中,除了第五位,其他位数字均相同。进一步的说就是当第五位数字为1时,此时为小写字母,当第五位数字为0时,此时为大写字母。那么利用这个特性,我们就可以通过刚刚学到的逻辑运算进行大小写转换:
assume cs:code ,ds:data
data segment
db 'a'
db 'b'
data ends
code segment
start :
mov ax,data
mov ds,ax
mov cx,2H
uppercase: mov al,ds:[bx] #转大写
and al,1011111B
mov ds:[bx],al
inc bx
loop uppercase
mov bx,0
lowercase: mov al,ds:[bx] #转小写
or al,0100000B
mov ds:[bx],al
inc bx
loop uppercase
mov ax,4c00H
int 21H
code ends
end start
end
结语
今天的内容就到此结束了,有疑问的小伙伴欢迎评论区留言或者私信博主,博主会在第一时间为你解答。
Spring通用架构及工具已上传到gitee仓库,需要的小伙伴们可以自取:
https://gitee.com/xiaolong-oba/common-base
屏幕前努力学习的你如果想要持续了解博主最新的学习笔记或收集到的资源,可以关注博主的个人公众号。这里有很多最新的技术领域PDF电子书及好用的软件分享
码字不易,感到有收获的小伙伴记得要关注博主一键三连,不要当白嫖怪哦~
如果大家有什么意见和建议请评论区留言或私聊博主,博主会第一时间反馈的哦。