汇编语言学习(三)

这部分是王爽《汇编语言》第7、8章重要内容的总结。主要分为四部分:

1.用汇编语言实现大小写字母的转换(and和or指令应用)
2.汇编语言二重循环的写法
3.数据处理的两个基本问题
4.实验七的思路与代码

实验七基本上是对之前学习内容的一个总结应用,比较重要。大小写字母转换部分帮助理解ASCII码设计的奇妙,二重循环用到栈也是很有意思。

1.and和or用法:

由于大写字母ASCII码二进制第5位为0,小写字母为1,所以可以通过andor实现的大小写字母转换。

通过与0操作,得到大写字母。或1操作,得到小写字母。

下面程序中需要注意的一点:

必须以al为中介,完成与和或的操作。

and [bx],11011111b的含义,不是[bx]这个字节单元与上11011111b,而是[bx]这个字单元与上0000000011011111b。所以需要al保证是字节的运算。

code segment
start:   mov ax,data
         mov ds,ax        
         mov bx,0
         mov cx,5
s:       mov al,[bx]
         and al,11011111b
         mov [bx],al
         inc bx
         loop s     
         mov cx,11
s1:      mov al,[bx]
         or al,00100000b
         mov [bx],al
         inc bx
         loop s1     
         mov ax,4C00h
         int 21h
code ends

2.编程,将datasg段中的每个单词改为大写字母。

涉及到的知识点:

如何编写二重循环?

主要解决的问题:

第一重循环中cx的值,应该如何保存?

解决方案:

1.放到寄存器中保存

但是寄存器数量有限,万一被占满该怎么办?

2.放到内存单元中保存

每次确定数据的地址非常麻烦。

3.放到栈中保存,通过push和pop就能解决问题
assume cs:code,ds:data,ss:stack
data segment
    db 'ibm             '
    db 'dec             '
    db 'dos             '
    db 'vax             '
data ends
stack segment
    dw 0,0,0,0,0,0,0,0
stack ends
code segment
start:  mov ax,data
            mov ds,ax
            mov ax,stack
            mov ss,ax
            mov sp,10h

            mov cx,4
            mov bx,0
s:          mov si,0
            push cx
            mov cx,3
s1:         mov al,[bx+si]
            and al,11011111b
            mov [bx+si],al
            inc si
            loop s1
            add bx,16
            pop cx
            loop s

            mov ax,4C00h
            int 21h
code ends
end start

3.数据处理的两个基本问题

1.处理的数据在什么地方?

立即数、寄存器、段地址和偏移地址

2.指令要处理的数据有多长?

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

用操作符X ptr 指明内存单元的长度,X在汇编指令中可以为word或byte。

add byte ptr [bx],2

add word ptr [bx],2

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

题目要求就是将一个公司从1975年到1995年的 年份、收入、雇员和人均收入的数据,按照一定格式保存在table段中。其中人均收入需要用收入除以雇员数。

table段,一共有14行,每一行16个字节。0~3字节存年份,5~8字节存收入,A~B字节存雇员数,D~E字节存人均收入。4、9、C、F字节存空格。

思路如下:

1.程序分为三段,data段、table段和code段。用ds记录data的段地址,es对应table,cs对应code。

2.code段中,在将数据复制到表格中时,需要每一行每一行处理。所以设置循环,使cx=21

3.bx指向table段的每一行,从0开始每次移动10h。[bx+idata]用于定位每行的元素位置。

4.bpsi用于锁定table段中每一行所需要的数据。

由于年份和收入每个数据项占用4个字节,而雇员每个数据项占用2个字节。所以bp每个循环增加4,bp指向当前行年份数据在data段的中位置,[bp+84]指向当前行收入数据在data段中的位置。而si每个循环增加2,指向当前行雇员数据在data段中的位置。

5.对于除法,要提前将收入数据的低位存在ax中,高位数据存在dx中。

6.注意转移过程中究竟一次转移几个字节,以及相应的写法。

具体代码如下:

assume cs:code,ds:data,es:table
data segment
   year    db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
           db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
           db '1993','1994','1995'
   income  dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
           dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000

   employeenum dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
               dw 11542,14430,15257,17800
data ends

table segment
    db 21 dup ('year summ ne ?? ')   
table ends 

code segment
start:  mov ax,data
            mov ds,ax
            mov ax,table
            mov es,ax

            mov bx,0
            mov bp,0
            mov si,0
            mov cx,21
s:          mov ax,[bp]
            mov es:[bx],ax
            mov ax,[bp+2]
            mov es:[bx+2],ax
            mov BYTE ptr es:[bx+4],20h
            mov ax,[bp+84]
            mov es:[bx+5],ax
            mov dx,[bp+86]
            mov es:[bx+7],dx
            mov BYTE ptr es:[bx+9],20h
            mov ax,[bp+168]
            mov es:[bx+10],ax
            mov ax,[bp+84]
            mov BYTE ptr es:[bx+12],20h
            div WORD ptr [si+168]
            mov es:[bx+13],ax
            mov es:[bx+15],20h
            add bp,4
            add bx,16
            add si,2
            loop s

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

程序的缺点在于,没有采用结构化的寻址表达形式:bx.idata[si],原因是把10进制换成16进制有些麻烦……

猜你喜欢

转载自blog.csdn.net/LJFYYJ/article/details/81158887