汇编笔记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

2地址内存单元存放的<字型>数据?       ==> 2和3连续   FF(高8位)78(低8位)H


1地址内存单元存放的<字节型>数据?    ==>  4EH

1地址内存单元存放的<字型>数据?       ==>784EH





二、数据的读取

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


add ds,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 = 01H


4.有内存如下: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

数据存放到哪里







0 0
原创粉丝点击