汇编笔记4
来源:互联网 发布:淘宝有趣搜索血滴子 编辑:程序博客网 时间:2024/05/21 05:06
一、内存中数据的长度
数据的长度:
Byte = 8bit (字节型数据) 一个内存地址就能保存一个字节
Word = 2Byte = 16bit (字型数据) 一个字需要2个地址连续的内存单元来存放 高位地址存放高位字节 低位地址存放低位字节
四个特殊的寄存器:他们可以各自分为互相独立的8位的寄存器
AX = AH + AL ==>AX 可以存放一个字型数据 或 存放2个字节型数据
BX = BH + BL
CX = CH + CL
DX = DH + DL
内存中内存单元是有编号的
0 1 2 3 4 5 6 7 8 9 A B C D E F 10H ............ 一个内存地址就能保存一个字节
例:假设内存中有如下
问:
0地址内存单元存放的<字节型>数据? ==> 20H
0地址内存单元存放的<字型>数据? ==>(一个字需要2个地址连续的内存单元来存放 高位地址存放高位字节 低位地址存放低位字节) 0和1连续 1相对于0是高位地址 所以 4E(高8位)20(低8位)H
2地址内存单元存放的<字节型>数据? ==> 78H
1地址内存单元存放的<字节型>数据? ==> 4EH
二、数据的读取
cpu把cs:ip指向的地址中的内容当作是指令
找到数据同样需要一个地址信息 ==> 段地址:偏移地址
ds --> 段寄存器 --> 里面保存段地址信息
将内存中的数据存放到寄存器
d 2000:0 查看2000H
e 2000:0 修改2000H
mov bx,2000H
mov ds,bx -->段地址就变成2000了
mov al,ds:[0] -->将 2000:0 这个位置的数据存放到al(8位寄存器)中 --> al决定了只取一个字节也就是字节型数据
这里不能写al,ds:[0] debug不允许 但是变成要这样写 mov al,[0] 默认的段地址就是ds
AL 寄存器 只能存放字节型数据
这里就是将 11H 存放到AL中
mov ax,ds:[0]
AX是16位的 取一个字型数据
高位地址存放高位字节 低位地址存放低位字节
22是高位字节 11 是低位字节
就是将2211H 存放到AX中
同理:mov ax,ds:[1] AX读取一个字型数据
将3322H 存放到AX中
mov bl,ds:[1]
mov dx,ds:[2] 16位寄存器 高位地址存放高位字节 低位地址存放低位字节
将0433H 存放到DX中
数据的长度取决于是 A(B,C,D)X (16位寄存器 字节型数据) 还是 A(B,C,D)H(L) (8位寄存器 字型数据)
将寄存器中的数据送入内存中
例: 将 al 中的数据送入内存单元10000H中
mov bx,1000H
mov ds,bx (ds是段地址 物理地址 = 段地址*10H +偏移地址)
mov ds:[0],al (这里物理地址就是 10000 H)
三、内存数据传送练习
1. 内存中的情况如图所示,指令执行后寄存器中的内容
mov ax,2000H AX = 2000H
mov dx,ax DX = 2000H
mov ax,ds[0] AX = 1123H -->将ds:[0]字型数据存放到AX
mov bx,ds[2] BX = 6622H -->将ds:[2]字型数据存放到BX
mov cx,ds:[1] CX = 2211H -->将ds:[1]字型数据存放到CX
add bx,ds[1] BX = 8833H -->将bx 和 ds:[0] 字型数据相加
add cx,ds[2] CX = 8833H -->将cx 和 ds:[2] 字型数据相加
2.内存中的情况如图所示,指令执行后寄存器中的内容
mov ax,2000H AX = 2000H
mov ds,ax DS = 2000H
mov ax,2C34H AX = 2C34H
mov ds:[0],ax 20000H 34H
20001H 2CH
mov bx,ds:[0] BX= 2C34H
sub bx,ds:[2] BX = BX - 1122H = 1B12 H
mov ds:[2],bx 20002H 12H
20003H 1BH
四、移动指令和运算指令的总结
移动指令
mov 寄存器,数据 -->将后面的数据放入寄存器中 例:mov ax,10H
mov 寄存器,寄存器 -->将后面寄存器中的内容放入前面的寄存器中 例:mov ax,bx
mov 寄存器,内存单元 -->前面的这个寄存器决定了后面取多少长度的数据 (字型数据据) 例:mov ax,ds:[0] 取字节型数据
mov 内存单元,寄存器 -->同样 寄存器决定了取多少长度的数据 例:mov ds:[0],bx
mov 段寄存器,寄存器 -->例:mov bx,1000H mov ds,bx 这样段地址就改变了
mov 寄存器,段寄存器 -->例:mov bx,ds
直接写mov ds,1000H 这是不允许的
运算指令
add 寄存器,数据 --> add ax,1H
add 寄存器,寄存器 --> add ax,bx
add 寄存器,内存单元 --> add ax,ds:[0] 字型数据的相加
add 内存单元,寄存器 --> add ds:[0],ax
sub 寄存器,数据 --> sub ax,1H
sub 寄存器,寄存器 --> sub ax,bx
sub 寄存器,内存单元 --> sub ax,ds:[0] 字型数据的相减
sub 内存单元,寄存器 --> sub ds:[0],ax
1. 写几条指令,将一段内存中连续的3个字型数据累加存放到ax中
mov bx,2000H
mov ds,bx
mov ax,0 要确保ax中是零
add ax,ds[0] --> ax = 3412H
add ax,ds[2] --> ax = BCABH
add ax,ds[4] --> BCABH + EEFFH = 1ABAAH --> ax = ABAAH
2.有内存如下:20000H = FFH
20001H = FFH
mov ax,FFFFH
mov bx,2000H
mov ds,bx
add ds:[0],ax FFFFH + FFFFH = 1FFFEH --> 20000H = FEH
20001H = FFH
3.有内存如下:20000H = FFH
mov al,10H
mov bx,2000H
mov ds,bx
add ds:[0],al FFH + 10H = 10FH 取后面两位 --> 20000H = 0FH 并不会产生进位 不会有20001H = 01H4.有内存如下:20000H = FFH
mov al,FFH
mov bx,2000H
mov ds,bx
add ds:[0],ax 两个字型相加 高位地址存放高位字节 低位地址存放地位字节 --> 20000H = 0FH 20001H = 01H
5. 在debug中,用"debug a:0 1F"查看内存,结果如下
0000:0000 78 80 F0 30 EF 60 30 E2 - 00 80 80 12 66 20 22 60
0000:0010 62 26 E6 D6 CC 2E 3C 3B - AB BA 00 00 26 06 66 88
写出下列指令执行后的寄存器的值
mov ax,1H AX = 1H
mov ds,ax DS = 1H
mov ax,ds:[0] ds *10H + 0H = 10H
字型数据 AX = 2662H
mov bx,ds:[1] 字型数据 BX = E626H
mov ax,bx AX = E626H
mov ax,ds:[0] 字型数据 AX = 2662H
mov bx,ds:[2] BX = D6E6H
add ax,bx 2662H + D6E6H = FD48H --> AX = FD48H
add ax,ds:[4] FD48H + 2ECCH = 12C14H --> AX = 2C14H
mov ax,0 AX = 0H
mov al,ds:[2] 字节型数据 AL = E6H -->AC = 00E6H
mov bx,0 BX = 0H
mov bl,ds:[c] 字节型数据 BL = 26H -->BX = 0026H
add al,bl 字节型数据相加 E6H + 26H = 10CH --> AL = 0CH --> AX = 000CH
5.内存中的情况如图所示
CS = 2000H IP = 0 DS = 1000H AX = 0 BX = 0
10000H B8H mov ax,2000H 20000H B8H mov ax,6622H
10001H 00 20001H 22H
10002H 20H 20002H 66H
10003H 8E mov ds,ax 20003H EAH jmp 0FF0H:0100H
10004H D8H 20004H 00H
10005H A1H mov ax,ds:[8] 20005H 01H
10006H 08H 20006H F0H
10007H 00H 20007H 0FH
10008H A1H mov ax,ds:[2] 20008H 89H mov bx,ax
10009H 02H 20009H C3H
1000AH 00H 2000AH
1000BH 2000BH
1.写出指令执行序列(用汇编指令写出)
1)cpu 从cs:ip组合出来地址读取指令,江都区的指令存入到指令缓存器中
2)ip = ip +所读指令字节数3)执行指令缓存器中的内容 重复过程
mov ax,6622H
jmp 0FF0H:0100H 0FF0H * 10H +100H = 10000H
mov ax,2000H
mov ds,ax
mov ax,ds:[8]
mov ax,ds:[2]
2.写出cpu执行每条指令后,cs:ip相关寄存器中的值
CS = 2000H IP = 0000H
CS = 2000H IP = 0003H
CS = 2000H IP = 0008H 曾经指向过 执行jmp 0FF0H:0100F之后cs:ip 变了
CS = 0FF0H IP = 0100H
CS = 0FF0H IP = 0103H
CS = 0FF0H IP = 0105H
CS = 0FF0H IP = 0108H
CS = 0FF0H IP = 010BH
五、内存访问形式 栈
栈
一段连续的内存空间,连续的内存地址
内存地址用段地址:偏移地址表示
和栈有关系的两个寄存器是ss(是保存段地址信息的)和sp(是保存偏移地址信息的)
段地址:偏移地址
ss sp 永远指向栈顶数据
入栈 push 字型数据 => 数据从哪里来
出栈 pop 字型数据 => 数据取出 到哪里
push指令: 首先将sp 减2 => 这样ss和sp组合成了一个新的地址ss:sp => 将从哪里来的字型数据存放到SS:SP
pop指令: 直接将ss:sp组合出来的地址里面的字型数据拿出去 到哪里 => 然后 sp +2
伪代码:
push 语文书
push 数学书
push 英语书
pop 书架1
pop 书架2
pop 书架3
push 寄存器 (ax bx cx dx ds es ss sp .......16bit 一个字型)
例: push ds:[0] -> 从ds:[0]拿一个字型数据
pop 寄存器
例:pop ax
栈在哪里和ss:ip有关 由程序员决定ss:ip
栈的大小也是由程序员决定的
六、栈的使用问题
程序员要自己注意注越界问题
临时性保存数据
1.利用栈交换 AX 和 BX 中的数据
push ax
push bx
pop ax
pop bx
2.假设AX = 001AH,BX = 001BH,然后删除成0,利用栈恢复AX和BX中的数据
mov bx,2000H
mov ss,bx
mov sp,10H
mov ax,001AH
mov bx,001BH
push ax
push bx
pop bx
pop ax
七、栈的极限
1. 一个栈能够存放最多多少个字型数据 32768
地址线 决定了 cpu的寻址能力
cpu中保存和栈有关系的地址信息的两个寄存器是段地址寄存器ss和偏移地址寄存器sp
ss : sp
sp限制了栈的寻址能力
偏移地址能表示 0~FFFFH
0~FFFFH 字节 = 65536个字节 = 32768 个字
所以一个栈能够存放32768个字
push 和 pop 操作 操作的是一个字型数据
怎么样设置一个栈的大小
关键是sp的设置
假设sp从0 开始 是ss:0 假设要设置的栈的大小是16个字节 也就是10H
ss:0 + 16 (10H) 那么我们要设置的SP = 10H 这样0~FH(10H -1) 就是我们设置的16个字节大小的栈
假设是从10H开始 ss:10 假设要设置的栈的大小也是16个字节
ss:10H + 16 (10H) 那么我们要设置的SP = 20H
当我们在使用push指令时 sp会每一次 减 2H 减小到10H的时候 如果我们再使用push指令 那就会覆盖到前面的数据
也就是造成了破坏 这叫越界
假设sp从0开始 ss:0 假设要设置的栈的大小是65536个字节 也就是10000H
ss:0 + 10000H 那我们要设置的SP = 0000H 取10000H 后四位 就是4个0
我们现在要执行push指令的话
push ax -> sp 减 2H ---> 0 减 2H = FFFFFFFFFFFFFFFEH --> 取后4位 --> sp = FFFEH
连续push 32768次之后再push就会越界 如果再push 一次 原来的数据就会被覆盖
2. 将10000H - 1000FH 中的8个字型数据 逆序复制到20000H - 2000FH
mov ax,2000H mov ds,ax
mov bx,2000H mov ss,bx
mov sp,10H
push ds:[0] push ds:[2] push ds:[4] push ds:[6]
push ds:[8] push ds:[A] push ds:[C] push ds:[E]
push 把 从哪里来的数据 放到栈ss:sp中
3. 将10000H - 1000FH 中的8个字型数据 逆序复制到20000H - 2000FH
mov ax,2000H mov ds,ax
mov bx,1000H mov ss,bx
mov sp,0
pop ds:[E] push ds:[C] push ds:[A] push ds:[8]
push ds:[6] push ds:[4] push ds:[2] push ds:[0]pop 把 栈中的数据送到 到哪里去
八、小结
cs:ip 和指令有关
ds:[0] [1] ........ 和数据有关
ss:ip 和临时性数据有关
数据在哪里
数据的长度 字节型数据 和 字型数据 AX BX CX DX AH AL BH BL CH CL DH DL
数据的处理 add sub
数据存放到哪里
- 汇编笔记4
- 汇编学习笔记---实验4
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编笔记
- 汇编学习笔记第4~10章:汇编原理-汇编指令实战
- 汇编学习笔记【4】之栈专题
- 8086汇编学习笔记4-指令
- 集合框架-去重字符串案例
- 面试12之给定两个链表ListNode* A,ListNode* B,请返回A+B的结果
- The CoderPai Day in AI
- C/C++——从ctime使用到随便测一样冒泡排序和堆排序的效率
- 键盘购买指南
- 汇编笔记4
- 《C和指针》——带副作用的宏参数
- 2017 Google hosts 持续更新
- 值类型和引用类型
- C++——二进制输出一个数以及输出double型位数过多情况
- 常用R语言包介绍
- C/C++——一个因为unsigned引发的大问题
- 模板实现双向链表
- python正则表达式系列(2)——re模块常用函数