【汇编语言】8086汇编字符串定义为何使用DB?其他数据类型不可以吗?(20200515复盘) 您所在的位置:网站首页 字节定义伪指令DB 【汇编语言】8086汇编字符串定义为何使用DB?其他数据类型不可以吗?(20200515复盘)

【汇编语言】8086汇编字符串定义为何使用DB?其他数据类型不可以吗?(20200515复盘)

2023-08-11 00:27| 来源: 网络整理| 查看: 265

目录 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 segment data1 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 segment data1 db 'dox' data ends

现在,你需要将'dox'修改为'DOX',应该如何做?如果要修改为'VEX',又该怎么做?

提示:

第一个问题,可以转换为小写字母变成大写字母的问题第二个问题,就是内存修改问题 你可以使用mov ax,'V'的方式,直接替换也可以先定义好data2 db 'VEX'数据,再进行替换 2 扩展:数据定义的方式

为了避免内容冗杂,我单独写了一篇文章,链接在此

我希望你知道的是,学会了字符串的定义,也就学会了各种数据的定义,因为字符串定义的本质,就是数字定义,只需要按照编码规则换成数字就行了。

3 附录:题目和回顾

来自于《汇编语言》(王爽)第七章,此处只是为了记录,读者可不看。

; 全变成大写字母,并且将外循环次数暂存到内存中 assume ds:data data segment data1 db 'abc gg ' data2 db 'hello hq ' cycleCount dw ? data ends assume ss:stack stack segment cycle dw ? stack ends assume cs:code code segment start: mov ax,data mov ds,ax mov ax,stack mov ss,ax ; 下面两条语句不能二合一,因为汇编程序追求的是格式的统一与极简 mov sp,offset cycle ; 不要使用 Magic Number sub sp,2 mov bx,0 ; 外层 控制行 mov cx,2 s0: ;mov cycleCount,cx ;push cycle ; 注意此处,不是推入偏移地址这个数据,push offset cycle,而是直接推入数据 ; 【数据传送】指令 ; 【错误!】推的是cx,不是cycle push cx mov si,0 ; 内层 控制列 mov cx,8 s1: ; 字传送,不浪费 mov ax,[bx][si] ; 为什么没有造成不匹配报错 【按照地址找数据,类型是自动匹配的】 ; 【自动匹配】【强制匹配】 and ax,0DFDFH mov [bx][si],ax add si,2 loop s1 add bx,16 ;mov cx,cycleCount pop cx loop s0 mov ax,4c00h int 21h code ends end start


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有