《汇编语言》- 读书笔记 - 第8章 - 数据处理的两个基本问题(阶段总结)

8.1 bx、si、di 和 bp (可用于内存寻址)

  1. 8086CPU 中,只有 这4个 寄存器可以用在[...]中来进行内存单元的寻址
    1.1. 这4个 寄存器都可以单独使用。
    1.2. 通常是单独使用 bxbp。在实现更复杂的内存寻址时,用 sidibxbp 组合。
    1.3. 还可以加立即数
  2. 允许的组合方式如下表:( bxbpsidi 不能直接组合 )
寄存器 单独使用 si组合 di 组合 立即数组合
bx [ bx ] [ bx + si ] [ bx + di ] [ bx + idata ]
[ bx + si + idata ]
pb [ pb ] [ pb + si ] [ pb + di ] [ pb + idata ]
[ pb + si + idata ]
  1. 使用 bx 时默认的段地址在 ds,如:mov ax, [bx]; mov ax, [bx+si]; mov ax, [bx+si+idata]
    使用 bp 时默认的段地址在 ss,如:mov ax, [bp]; mov ax, [bp+si]; mov ax, [bp+si+idata]
    3.1. 如果需要在其他段中寻址,则需要显式地指定相应的段前缀,如:
    mov ax, es:[bx]; mov ax, es:[bx+si]; mov ax, es:[bx+si+idata]
    mov ax, cs:[bx]; mov ax, cs:[bx+si]; mov ax, cs:[bx+si+idata]

8.2 机器指令处理的数据在什么地方

3 个地方:CPU内部内存接口(将在后面的课程中进行讨论)

  • 表 8.1 指令举例
机器码 汇编指令 指令执行前数据的位置
8E1E0000 mov bx,[0] 内存,ds:0 单元
89C3 mov bx,ax CPU 内部,ax 寄存器
BB0100 mov bx,1 CPU 内部,1 在指令缓冲器中

8.3 汇编语言中数据位置的表达

汇编语言中用 3 个概念来表达数据的位置

1. 立即数(idata)

直接写在代码中的数据,在汇编语言中称为: 立即数。(它们执行前在 CPU 的指令缓冲器中)
可以简单的理解为汇编语言的字面量(只是类似,不是同相)。

mov ax,1
add bx,2000h
or bx,00010000b
mov al,'a'

2. 寄存器

指令要处理的数据寄存器中,在汇编指令中给出相应的寄存器名

mov ax,bx
mov ds,ax
push bx
mov ds:[0],bx
push ds
mov ss,ax
mov sp,ax

3. 段地址(SA)和偏移地址(EA)

要处理的数据在内存时,汇编指令中可用[X]的格式指出 EA、SA 在某个段寄存器中。

8.4 寻址方式

计算内存单元偏移地址方法称为寻址方式
在这里插入图片描述

8.5 指令要处理的数据有多长(如何定义)

8086CPU指令,可以处理 byte(8位) 和 word(16位) 两种尺寸的数据。

1. 通过:寄存器名

  1. 通过寄存器名知晓数据的尺寸。

使用AX、BX、CX、DX 这些16位寄存器,说明数据尺寸为,如:

mov ax,1
mov bx,ds:[0]
mov ds,ax
mov ds:[0],ax
inc ax
add ax,1000

使用ah、al、bh、bl、ch、cl、dh、dl 这些8位寄存器,说明数据尺寸为字节,如:

mov al,1
mov al,bl
mov al,ds:[0]
mov ds:[0],al
inc al
add al,100

2. 通过:操作符 word ptrbyte ptr

在没有寄存器名存在的情况下,可以用操作符 X ptr 指明内存单元的长度,X 在汇编指令中可以为 wordbyte

# 用 word ptr 指明访问的内存单元是一个字单元
mov word ptr ds:[0],1
inc word ptr [bx]
inc word ptr ds:[0]
add word ptr [bx],2

# 用 byte ptr 指明访问的内存单元是一个字节单元
mov byte ptr ds:[0],1
inc byte ptr [bx]
inc byte ptr ds:[0]
add byte ptr [bx],2
  • 书上的例子:
    假设我们用 Debug 查看内存的结果如下:
    2000:1000 FF FF FF FF FF FF ......
    使用 byte ptr 修改 2000:1000 位置 值 = 1 结果为
    2000:1000 01 FF FF FF FF FF ......
    使用 word ptr 修改 2000:1000 位置 值 = 1 结果为
    2000:1000 01 00 FF FF FF FF ......

3. 其它方法

有些指令默认了访问的是单元还是字节单元,
比如:push [1000H]无需指明访问数据的尺寸,因为 push 指令只进行操作。

8.6 寻址方式的综合应用

8086CPU提供了[bx+si+idata]的寻址方式,便于结构化数据的处理。

  1. bx:定位整个结构体,
  2. idata:定位结构体中的某一个数据项
  3. si:定位数组项中的每个元素。

且汇编语言提供了更为贴切的书写方式,如:[bx].idata[bx].idata [si]
对应C语言中的变量.数据项[字符]。如书中的C代码示例声明了这样一个结构体:

struct company {
   	/*声明一个公司记录的结构体*/
	char cn[3];		/*公司名称*/
	char hn[9];		/*总裁姓名*/
	int pm;			/*排名*/
	int sr;			/*收入*/
	char cp[3];		/*著名产品*/
}
/*定义一个公司记录的变量,内存中将存有一条公司的记录*/
struct company dec={
    "DEC", "Ken Olsen", 137, 40, "PDP" };

8.7 指令 div

  1. 除数:可以是816位。可放存在寄存器内存
  2. 被除数:可以是1632位。
    2.1. 如果是16位,放在AX中。如果32位高16位DX
    2.2. 在DIV操作中被除数是用16还是32取决于除数用多少位来运算:
         除数用8位则被除数16位
         除数用16位则被除数32位
被除数 位数 AX DX
2 16位 00000000 00000010
65536 32位 00000000 00000000 00000000 00000001
  1. 结果:也取决于除数用多少位来运算。
    3.1. 除数用8位则。ALAH余数
    3.2. 除数用16位则。AXDX余数
除数 余数
8位 AL AH
16位 AX DX

8.8 伪指令 db、dw、dd

缩写 全称 含义 位数
db define bytedata byte 定义字节(1个字节)的数据 8
dw define worddata word 定义字(2个字节)的数据 16
dd define doubleworddata doubleword 定义双字(4个字节)的数据 32

问题 8.1

div 计算 data 段中第一个数据除以第二个数据后的结果,商存在第三个数据的存储单元中。

data segment
	dd 100001		; 被除数      dword(双字)32 位
	dw 100			; 除数        word ()16 位
	dw 0			; 存商的位置
data ends
  • 分析
    data 段中 dd 定义是被除数,做除法之前:
  1. data:0 字单元中的低 16 位存储在 ax
  2. data:2 字单元中的高 16 位存储在 dx
mov ax,data
mov ds ,ax
mov ax,ds:[0]			; ds:0 双字单元中的低 16 位存储在 ax 中
mov dx,ds:[2]			; ds:2 双字单元中的高 16 位存储在 dx 中
div word ptr ds:[4]		; 用 dx:ax 中的 32 位数据除以 ds:4 字单元中的数据
mov ds :[6],ax			; 将商存储在 ds:6 字单元中

1. 完整代码
assume cs:codesg, ds:data
data segment
	dd 100001				; 被除数 dword(双字)32 位
	dw 100					; 除数   word ()16 位
	dw 0					; 存商的位置
data ends

codesg segment
	mov ax,data				; 设置代码段位置。先用 ax 中转一手,才能装入 ds
	mov ds,ax
							; 读取 32位 双字节 被除数存入寄存器 dx:ax
	mov ax,ds:[0]			; 从 ds:0 处开始读取低 16'86A1' 存入 ax 中
	mov dx,ds:[2]			; 从 ds:2 处开始读取高 16'0001' 存入 dx 中
	div word ptr ds:[4]		; 用 dx:ax 中的 32 位数据除以 ds:4 字单元中的数据
	mov ds:[6],ax			; 将商存储在 ds:6 字单元中
codesg ends
end
2. 执行后在 debug 中反编译看下

u cs:0 002F 查看从程序开始到 002F 部分反编译结果。

  1. 我当前的学习环境,应该是没有任何额外的引导或启动代码的,所以程序通常从CS:0000H处开始执行。
  2. -u命令忘记了的话要可以回顾一下:Debug的使用
  3. 使用 -u命令查看反汇编结果时,可以看到数据段部分也显示了对应的汇编代码,但这只是debug自作多情罢了。因为这段内容只会被当作数据读取。虽然可以一根筋的把它翻译成汇编代码,但是然并卵,它只是一段数据。

在这里插入图片描述

3. 执行一下查看内存中数据段

在这里插入图片描述

  • 我们分析一下 dd 100001 另外两个同理。
    10进制 100001 转16进制后是 186A1
    由于声明的是双字节有32位,所以高位要补零,得到:00 01 86 A1
    然后先低后高保到内存里就是 A1 86 01 00

在这里插入图片描述

8.9 操作符 dup

dup 操作符在汇编语言中是一个用于简化定义重复数据的操作符。
它通常与数据定义伪指令(如 db、dw、dd 等)结合使用,以指定重复特定模式的数据块的次数

指令 描述 生成的数据
db 5 dup(0) 定义5个字节,每个字节的值都为0 00 00 00 00 00
dw 3 dup(0x1234) 定义6个字节(因为dw是定义字,占两个字节),每个字的值都是0x1234 34 12 34 12 34 12
dd 2 dup(0x12345678) 定义8个字节(因为dd是定义双字,占四个字节),每个双字的值都是0x12345678 78 56 34 12 78 56 34 12
db 4 dup(1, 2, 3) 定义12个字节,按照序列1、2、3重复四次 01 02 03 01 02 03 01 02 03 01 02 03
————————————

实验 7 寻址方式在结构化数据访问中的应用

《汇编语言》- 读书笔记 - 实验 7 寻址方式在结构化数据访问中的应用

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-25 18:34:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-25 18:34:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-25 18:34:01       82 阅读
  4. Python语言-面向对象

    2024-01-25 18:34:01       91 阅读

热门阅读

  1. rust for循环步长-1,反向逆序遍历

    2024-01-25 18:34:01       63 阅读
  2. Spring-注解开发

    2024-01-25 18:34:01       61 阅读
  3. ChatGPT 和文心一言哪个更好用?

    2024-01-25 18:34:01       60 阅读
  4. Abaqus许可分析方法

    2024-01-25 18:34:01       60 阅读
  5. leetcode-200-岛屿问题

    2024-01-25 18:34:01       62 阅读
  6. Vue3生命周期和Vue2生命周期对比

    2024-01-25 18:34:01       61 阅读