抄书笔记-汇编语言 第八章 数据处理的两个基本问题

通过前面的学习,我们知道,在处理数据的时候,有两个基本的问题需要解决:

  1. 处理的数据在什么地方?
  2. 要处理的数据有多长?

我们定义个reg来表示寄存器,sreg来表示段寄存器:

reg主要包括:ax,bx,cx,dx,ah,al,bh,bl,ch,cl,dh,dl,sp,bp,si,di

sreg主要包括:ds,ss,es,cs

8.1bx,si,di,和bp

  1. 在8086cpu中,只有这四个寄存器可以使用[]方式来进行内存单元的寻址。
  2. 在[]寻址中,这4个寄存器可以单独出现,或者以4中组合出现:bx和si,bx和di,bp和si,bp和di 不能出现bx和bp,si和di
  3. 只要在[]中使用了bp,而没有显式地指明段寄存器的话,默认的地址是存在ss里面。

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

绝大多数的机器指令都是数据处理的指令,处理类型可以分为3类,读取,写入,运算。机器指令并不关心数据的值是多少,而关心指令执行前一刻。

所需要处理的数据在3个地方:

  1. cup内部
  2. 内存
  3. 端口

指令举例:

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

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

(1)立即数(idata)

对于直接包含在机器指令中的数据(执行前的一刻是在CPU的指令缓冲器中),在汇编语言中称为:立即数(idata),在汇编指令中直接指出。

(2)寄存器

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

如:mov ax,bx

mod ds,ax

push bx

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

指令要处理的数据在内存中,在汇编指令中可以使用[bx]的方式给出EA,SA在某一个段寄存器中,存放地址的寄存器是可以默认的。

如:mov ax,[0]

mov ax,[di]

mov ax,[bx+1]

默认的段寄存器是在ds中

如:mov bx,[bp]

mov ax,[bp+8]

默认的段寄存器是在ss中(只要包含bp的内存地址,段地址就是在ss中)

8.4寻址方式

当数据存放在内存中的时候,我们可以使用多种方式来给出这个内存单元的偏移地址,这种定位内存单元的方法一般被称为寻址方式。

主要的方式有:

  1. 直接寻址
  2. 寄存器间接寻址
  3. 基地址变址寻址
  4. 相对基地址变址

8.5指令要处理的数据有多长

在8086CPU中,可以处理两种尺寸的数据,byte和word,所以在机器指令中要指明,指令进行的是字操作还是字节操作,需要在汇编中给出:

(1)通过寄存器名指明要处理的数据的尺寸

(2)在没有寄存器名的情况下面,需要使用X ptr指明内存单元的长度,X在汇编指令可以是word或者byte。

如:mov word ptr ds:[0],1

mov byte ptr ds:[0],2

(3)其他的方法

有些指令默认了访问的地址是字单元还是字节单元,比如 push 命令只能进行字操作。

8.6寻址方式的综合使用

修改公司的数据问题:

汇编的实现:

mov ax,seg
mov ds,ax
mov bx,60h

mov word ptr [bx,0ch],38
add word ptr [bx,0eh],70

mov si,0
mov word ptr [bx+10h+si],'V'
inc si
mov word ptr [bx+10h+si],'A'
inc si
mov word ptr [bx+10h+si],'X'

如果使用c来实现

struct company{
    char cn[3];
    char hn[9];
    int pm;
    int sr;
    char cp[3];
}

struct company desc={"DEC","Ken Olsen",137,40,"PDP"};

main(){
    int i;
    dec.pm=38;
    dec.sr=dec.sr+70;
    i=0;
    dec.cp[i]='V';
    i++;
    dec.cp[i]='A';
    i++;
    dec.cp[i]='X';
    return 0;
}

按照c的风格来写汇编:

mov ax,seg
mov ds,ax
mov bx,60h
mov word ptr [bx].0ch,38
add word ptr [bx].0eh,70
mov si,0
mov byte ptr [bx].10h[si],'V'
inc si
mov byte ptr [bx].10h[si],'A'
inc si
mov byte ptr [bx].10h[si],'X'

一般来说,我们可以使用[bx+idata+si]的方式来访问结构体中的数据,用bx来定位整体,用idata来定位结构体中的某一个数据项,用si来定位数组项中的每一个元素。

8.7div指令

div是除法指令,使用时应该注意的问题有:

(1)除数:有8位和16位两种,在一个reg或者内存中

(2)被除数:默认是在AX或者DA和AX中,如果除数为8位,则被除数是16位,默认是在AX中,如果除数是16位,被除数是32位,在DX和AX中,DX存放高16位,AX存放低16位。

(3)结果:如果除数是al的话,商保存在al,余数保存在ah里面,如果除数是16位的话,商保存在ax里面,余数保存在dx里面。

格式如下:

div reg

div 内存单元

比如:

div byte ptr ds:[0]

含义:

 (al)=(ax)/((ds)*16+0)的商
 (ah)=(ax)/((ds)*16+0)的余数

编程计算100001/100

分析:被除数100001大大于65535,不能使用AX来存放,只能用DX和AX来存放,也就是进行16位的除法,被除数是100小于255,本来是可以使用一个8位寄存器来存放的,但是因为被除数是32位的,要求除数是16位的。只能用一个16位的寄存器来存放了。

 mov dx,1
 mov ax,86A1H
 mob bx,100
 div bx

##8.8伪指令dd

前面我们使用了db,dw来定义字节型数据和字数据,dd用来定义dword(double word双字)型的数据。

 data segment
    db 1
    dw 1
    dd 1
 data ends

在data中定义了三个数据:

第一个数是01H,在data:0处,占据一个字节

第二个数是0001H,在data:1处,占据一个字

第三个数是00000001H,在data:3处,占据2个字

用div计算data段中第一个数据除以第二个数据后的结果,结果保存在第三个数据中。

 data segment
    dd 1000001
    dw 100
    dw 0
 data end

代码实现:

mov ax,data
mov ds,ax
mov ax,ds:[0]
mov dx,ds:[2]
div word ptr ds:[4]
mov ds:[6],ax

8.9dup

dup在汇编中和dd,db,dw一样,也是由汇编程序识别的处理的符号,它是和db,dd,dw等配合使用的,用来进行数据的重复。

db 3 dup (0)

定义了三个字节,他们的值都是0,相当于 db 0,0,0

db 3 dup (0,1,2)

定义了九个字节,他们的值分别是:0,1,2,0,1,2,0,1,2

相当于:db 0,1,2,0,1,2,0,1,2

可见dup的使用格式如下:

db 重复的次数 dup (重复的数据类型的值)

这个对于定义大量的字节数据来说是非常有用的:

data segment
    db 200 dup (0)
data ends

共有 0 条评论

Top