汇编语言寻址方式的综合应用

http://www.511yj.com/asm-x86-49.html
下面我们通过一个问题来进一步讨论一下各种寻址方式的作用

关于DEC公司的一条记录(1982年)如下。
公司名称:DEC
总裁姓名:Ken Olsen
排名:137
收入:40(40亿美元)
著名产品:PDP(小型机)
这些数据在内存中以图8.1所示的方式存放。

可以看到,这些数据被存放在seg段中从偏移地址60H起始的位置,从seg:60起始以ASCII字符的形式存储了3个字节的公司名称:从seg:60+3起始以ASCII字符的形式存储了9个字节的总裁姓名;从seg:60+OC起始存放了一个字型数据,总裁在富翁榜上的排名;从seg:60+0E起始存放了一个字型数据,公司的收入;从seg:60+ 10起始以ASCII字符的形式存储了3个字节的产品名称。

511遇见

以上是该公司1982年的情况,到了1988年DEC公司的信息有了如下变化。
(1) Ken Olsen在富翁榜上的排名己升至38位;
(2) DEC的收入增加了70亿美元;
(3)该公司的著名产品己变为VAX系列计算机。
我们提出的任务是,编程修改内存中的过时数据。
首先,我们应该分析一下要修改的数据。
要修改内容是:
(1) (DEC公司记录)的(排名字段)
(2) (DEC公司记录)的(收入字段)
(3) (DEC公司记录)的(产品字段)的(第一个字符)、(第二个字符)、(第三个字符)

从要修改的内容,我们就可以逐步地确定修改的方法。

(1)要访问的数据是DEC公司的记录,所以,首先要确定DEC公司记录的位置:
R=seg:60
确定了公司记录的位置后,下面就进一步确定要访问的内容在记录中的位置。
(2)确定排名字段在记录中的位置:0CH
(3)修改R+0CH处的数据。
(4)确定收入字段在记录中的位置:0EH
(5)修改R+0EH处的数据。
(6)确定产品字段在记录中的位置:10H
要修改的产品字段是一个字符串(或一个数组),需要访问字符串中的每一个字符。所以要进一步确定每一个字符在字符串中的位置。
(7)确定第一个字符在产品字段中的位置:P=O
(8)修改R+1 OH+P处的数据;p=p+l
(9)修改R+IOH+P处的数据; p=P+1
(10)修改R+0H+P处的数据

assume cs:codesg,ds:datasg

;数据段存储原始数据
datasg segment
  db 'DEC'          ;公司名称(+00H)
  db 'Ken Oslen'     ;总裁姓名(+03H)
  dw 137            ;排名(+0CH)
  dw 40            ;收入(40亿美元)(0EH)
  db 'PDP'          ;著名产品(10H)
datasg ends

;代码段
codesg segment
start: mov ax,seg
    mov ds,ax
    mov bx,0                       ;记录首址送BX

    mov word ptr[bx+0ch],38      ;寄存器相对寻址修改排名为38
    mov word ptr[bx+0eh],70      ;寄存器相对寻址修改收入

    mov si,0                       ;用si来定位产品字符串中的字符
    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'

    mov ax,4c00h
    int 21h
codesg ends
end start

如果你熟悉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,"PDF"};
​
int 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';
}

对比代码:

mov ax,seg
mov ds,ax
mov bx,60h 
mov word ptr [bx+0ch],38       ;C: dec.pm = 38;
add word ptr [bx+0eh],70       ;C: dec.sr = dec.sr + 70;
​
mov si,0                       ;C: i = 0;
mov byte ptr [bx+10h+si],'V'   ;C: dec.cp[i] = 'V';
inc si                         ;C: i++;
mov byte ptr [bx+10h+si],'A'   ;C: dec.cp[i] = 'A';
inc si                         ;C: i++;
mov byte ptr [bx+10h+si],'X'   ;C: dec.cp[i] = 'X';x

我们可以看到,8086CPU提供的如[bx+si+idata]的寻址方式为结构化数据的处理提供了方便。使得我们可以在编程的时候,从结构化的角度去看待所要处理的数据。从上面可以看到,一个结构化的数据包含了多个数据项,而数据项的类型又不相同,有的是字型数据,有的是字节型数据,有的是数组(字符串)。一般来说,我们可以用[bx+idata+si]的方式来访问结构体中的数据。用bx定位整个结构体,用idata定位结构体中的某一个数据项,用si定位数组项中的每个元素。为此,汇编语言提供了更为贴切的书写方式,如:

[bx].idata, [bx].idata[si]

在C语言程序中我们看到,如:dec.cp[i] ,dec是一个变量名,指明了结构体变量的地址,cp是一个名称,指明了数据项cp的地址,而i用来定位cp中的每一个字符。汇编语言中的做法是:bx.l0h[si]。看一下,是不是很相似?


发布日期:

所属分类: 编程 标签:


没有相关文章!