目录
- 0 前言
- 0.1 先告诉你结论
- 1 8086汇编语言中的字符串
- 1.1 字符串的定义与使用
- 1.2 直接定义的细节
- 1.2.1 使用DB数据类型
- 1.2.2 使用其他数据类型
- 1.3 直接使用的细节
- 1.3.1 赋值给寄存器
- 1.3.2 赋值给内存单元
- 1.3.3 字符串直接使用的本质
- 1.4 应用
- 2 扩展:数据定义的方式
- 3 附录:题目和回顾
0 前言
本文使用emu8086软件进行8086汇编语言编辑和运行。
顺便说一句,汇编语言源程序中的数字,默认是十进制,因此使用十六进制的数字的时候,必须有h或H后缀,本文也都遵循这样的原则。
至于为什么默认十进制,我只能说,编译器默认你是个人(不要笑!事实如此,如果默认你是机器,那么数字就默认十六进制了)。
0.1 先告诉你结论
在8086汇编语言中,定义字节类型的数据,比如
- 字符
- 字符串
- 字节数值数组
都用DB进行定义,表示其后的数据都是字节型数据,并且按照顺序依次存储。
举例说明:
db 'a'
db 'abcdefghijk' ; 相当于 db 'a','b','c','d'……
db 0,1,2,3,4,5,6,7
1 8086汇编语言中的字符串
通常情况下,汇编语言中的字符串,都会被赋予DB
(字节)数据类型,那么,为什么这样做?
不能使用DW数据类型吗?
当然可以,但是不建议使用。
1.1 字符串的定义与使用
- 定义后使用:可以在任何位置这样定义,不过建议在数据段内定义,然后再通过一些方式访问并使用它们
data1 db 'hello'
data2 db 'world'
- 直接使用:可以在指令中作为立即数直接使用
mov ax,'ab'
1.2 直接定义的细节
1.2.1 使用DB数据类型
使用DB作为数据类型的时候,字符串长度不受限制,默认字符串的每一个字符占一个字节,并且存储过程中,是按照一个字符占一个字节的方式,顺序依次存储的。
源程序如下:
assume ds:data
data segmentdata1 db 'abcchsadhkjhsfaksaskhasf'data ends
对应的内存单元,原来是这样的
0710:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0710:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0710:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
放入代码段数据之后是
0710:0000 61 62 63 63 68 73 61 64-68 6B 6A 68 73 66 61 6B abcchsadhkjhsfak
0710:0010 73 61 73 6B 68 61 73 66-00 00 00 00 00 00 00 00 saskhasf........
0710:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
这里,data1
的值将会被编译为这串字符串的首地址对应的偏移地址,也就是0000
,此时,data1并不能够代表字符串的全部字符,你可以把它理解为data1 db 'a'
,也就是第一个字符a是字节型数据,它的标号是data1,但是它后面的字符是没有标号的。
这也就意味着,mov ax,data1
会报错,因为data1是字节型数据,而mov al,data1
会得到al = 61H
。
将字符串规定为字节类型,是常用的,其他的了解即可,基本不会用到,下面简单介绍。
1.2.2 使用其他数据类型
例如使用dw
数据类型,则最多存储2个字节。
data1 dw 'ab'
也就是说,如果不是db类型的字符串,则存储字符的数量,是与数据类型相关联的,例如dw 'abc'
就是错误的,因为超越了2个字节。
对于其他数据类型,dd
、dq
等也是一样的,不过这些并不常用。
1.3 直接使用的细节
对于8086CPU来说
- 寄存器最大16位,也就是2个字节,比如
ax
,或者也可以是8位,比如al
- 可以操作的内存单元,也是如此,最大是
word ptr ds:[address]
(16位),或者byte ptr ds:[address]
(8位)
如果你想说32位或者更多,那是间接完成,也需要通过16位辅助来完成,我们这里说的是一步到位,直接使用。
这也就意味着,我们使用的字符串,只能使用'a'
或者'ab'
,这里的字母代表任何ASCII字符,在ASCII码中,一个字符占1个字节,所以我们只有这两种选择,并且,要注意数据类型的匹配,比如mov al,'ab'
就是非法的,mov ax,'abcd'
也是非法的。
我来列举一些常见情况,至于其他情况,都是其衍生品罢了。
1.3.1 赋值给寄存器
汇编语言程序为
mov al,'a'
mov ax,'a'
mov ax,'ab'
对于以上3条,编译后的结果是
mov al,061h
mov ax,00061h
mov ax,06162h
执行后的结果是
al = 61h
ax = 0061h
ax = 6162h
1.3.2 赋值给内存单元
这里,假设ds = 1000h
汇编语言程序为(注意,要加上数字h!,目的是为了美观)
mov byte ptr ds:[0],'a'
mov word ptr ds:[10h],'a'
mov word ptr ds:[20h],'ab'
编译后的结果为
mov byte ptr [10000],061h
mov word ptr [10010],00061h
mov word ptr [10020],06162h
执行前内存为
1000:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
1000:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
1000:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
执行后内存为
1000:0000 61 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 a...............
1000:0010 61 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 a...............
1000:0020 62 61 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ba..............
思考:你是不是发现了什么规律,是不是对于某些地方也感到困惑?思考一下,然后再往下看
1.3.3 字符串直接使用的本质
就一句话,将字符按照ASCII码规则,转换为数字,这个数字可以理解为立即数,其余的事情,就是立即数相关问题了。
你可能看见了,当mov word ptr ds:[20h],'ab'
之后,内存中是ba
而不是ab
,我想你知道原因了,这与在数据段定义不同,那里是顺序的,这里是倒序的,原因在于,在数据段用db数据类型存储,是一个一个字符存储的,而这里是作为一个字来存储的,是一个整体。
1.4 应用
思考题: 如果你有以下数据段的定义
assume ds:data
data segmentdata1 db 'dox'data ends
现在,你需要将'dox'
修改为'DOX'
,应该如何做?如果要修改为'VEX'
,又该怎么做?
提示:
- 第一个问题,可以转换为小写字母变成大写字母的问题
- 第二个问题,就是内存修改问题
- 你可以使用
mov ax,'V'
的方式,直接替换 - 也可以先定义好
data2 db 'VEX'
数据,再进行替换
- 你可以使用
2 扩展:数据定义的方式
为了避免内容冗杂,我单独写了一篇文章,链接在此
我希望你知道的是,学会了字符串的定义,也就学会了各种数据的定义,因为字符串定义的本质,就是数字定义,只需要按照编码规则换成数字就行了。
3 附录:题目和回顾
来自于《汇编语言》(王爽)第七章,此处只是为了记录,读者可不看。
; 全变成大写字母,并且将外循环次数暂存到内存中
assume ds:data
data segmentdata1 db 'abc gg 'data2 db 'hello hq 'cycleCount dw ?data endsassume ss:stack
stack segmentcycle dw ? stack endsassume cs:code
code segment
start:mov ax,datamov ds,axmov ax,stackmov ss,ax ; 下面两条语句不能二合一,因为汇编程序追求的是格式的统一与极简mov sp,offset cycle ; 不要使用 Magic Numbersub sp,2mov bx,0 ; 外层 控制行mov cx,2s0:;mov cycleCount,cx;push cycle ; 注意此处,不是推入偏移地址这个数据,push offset cycle,而是直接推入数据; 【数据传送】指令; 【错误!】推的是cx,不是cyclepush cx mov si,0 ; 内层 控制列mov cx,8s1: ; 字传送,不浪费mov ax,[bx][si] ; 为什么没有造成不匹配报错 【按照地址找数据,类型是自动匹配的】; 【自动匹配】【强制匹配】and ax,0DFDFHmov [bx][si],axadd si,2loop s1add bx,16;mov cx,cycleCountpop cxloop s0mov ax,4c00hint 21h
code ends
end start