博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
内存单元的寻址方式04
阅读量:5272 次
发布时间:2019-06-14

本文共 5070 字,大约阅读时间需要 16 分钟。

第六章

dw是定义字型数据,define word的缩写
---
assume cs:code
code segment
start: dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
mov bx,0
mov ax,0
mov cx,8
s:add ax,cs:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
----------
0123h,0456h,0789h,0abch....这些数据是存放在哪里的。是存放在当前代码段中,段地址:偏移地址,是cs:[0]开始;可以用debug加载程序,利用d命令查看内存情况
-----------------
将内存的数据放入栈中;需要定义栈的段地址,栈顶的位置,这里的栈顶的位置是30h,[0]-[15]存放着内存数据,栈空间是从[16]-[31]也就是20h-2fh,栈顶就是2fh+1也就是30h位置;
assume cs:codesg

codesg segment

dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
start: mov ax,cs
mov ss,ax
mov sp,30h
注释:程序中的数据是存放在代码段中的,所以,cs是段地址,也就是栈空间的段地址,栈顶的位置是30h;
mov bx,0
mov cx,8
s: push cs:[bx]
add bx,2
loop s
注:利用循环将,前16个字节的数据放入到栈中
mov bx,0
mov cx,8
s0: pop cs:[bx]
add bx,2
loop s0
注:依次从栈中将数据取出,存放在[0]-[15]单元中
mov ax,4c00h
int 21h
codesg ends
end start
--------------------
3、将数据、代码、栈放入不同的段中
定义不同的段,代码段为code,数据段为data,栈端为stack
assume cs:code,ds:data,ss:stack

data segment

dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
data ends

stack segment

dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends

code segment

start: mov ax,stack
mov ss,ax
mov sp,20h
mov ax,data
mov ds,ax
mov bx,0
mov cx,8
s: push [bx]
add bx,2
loop s
mov bx,0
mov cx,8
s0: pop [bx]
add bx,2
loop so
mov ax,4c00h
int 21 h
code ends
end start
--------------
第七章更灵活的定位内存地址的方法
1、and和or指令
and的指令是与,按位进行运算,全部为1,才是1,否则为0;如:0110与1010,结果是0010;
mov al,01100011B
and al,00111011B
执行结果:al=00100011B
or的指令是或,只要一个值是1,那么就是1,两个都是0才是0;
mov al,01100011B
or al,00111011B
执行后,al=01111011B
----
2、关于ASCII码
比如单词"desk"存储在计算机里的信息是二进制,,而计算机要将这些存储的信息再显示给我们看,就要对其进行解码。
按一下键盘'a'时,计算机会经过的流程:按下a键,这个按键的信息被送入计算机,计算机用ASCII码规则对其进行编码,将其转化为61H存储在内存的指定空间中;文本编辑软件从内存中取出61H,将其送到显卡上的显存中;工作在文本模式下的显卡,用ASCII码的规则解释显存中的内存,61h被当做字符'a',显卡驱动显示器,将字符'a'的图像画在屏幕上。
----------------
3、以字符形式给出的数据
在汇编程序汇总,用'....'的方式指明数据是以字符的形式给出的。
assume cs:code,ds:data

data segment

db 'unIX'
db 'foRK'
data ends

code segment

start: mov al,'a'
mov bl,'b'
mov ax,4c00h
int 21h
code ends
end start
r命令后,查看到寄存器ds=1503,ss=1513,cs=1514,其他的寄存器就省略;程序是从1513开始,因为1503-1513之间有256字节是与系统的交互数据段
所以data段是程序中第一个段,所以它就在程序的起始处,所以它的段地址是:1513:0,这里cs代码段是cs=1514;
注:db 'unIX'相当于'db 75H,6EH,49H,58H','u','n','I','X'的ASCII码分别为75H,6EH,49H,58H;内存中也是这样呈现的。
assume cs:codesg,ds:datasg

datasg segment

db 'BaSiC'
db 'iNfOrMaTiOn'
datasg ends

codesg segment

start: mov ax,datasg
mov ds,ax
mov bx,0
mov cx,5
s: mov al,[bx]
and al,11011111B
mov [bx],al
inc bx
loop s
mov bx,5
mov cx,11
s0: mov al,[bx]
or al,00100000B
mov [bx],al
inc bx
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
--------
字母大小写转换;通过ASCII码:
大写 十六进制 二进制
A 41 01000001
B 42 01000010
..................
小写 十六进制 二进制
a 61 01100001
b 62 01100010
...........
两种规律,它们十六进制相差20H,二进制就是第6位大写的是0,小写的是1,可以用指令:
小写转换大写:A and 11011111B;01000001B and 11011111B执行结果:01000001;
大写转换为小写;01000001B or 00100000B 执行结果:01100001;这是利用and与or指令加上二进制的规则来进行大小写字母的转换;
-----------------------
5、[bx+idata]
[bx]的方式指明一个内存单元,还可以用一种更为灵活方式来指明内存单元:[bx+idata];[bx+200]表示将bx的数值加上200;该指令常用形式的格式
mov ax,[200+bx]
mov ax,200[bx]
mov ax,[bx].200
-------------
6、用[bx+idata]的方式进行数组的处理
assume cs:codesg,ds:datasg

datasg segment

db 'Basic'
db 'MinIX'
datasg ends

codesg segment

start: mov ax,datasg

mov ds,ax
mov bx,0
mov cx,5
s: mov al,[bx]
and al,11011111B
mov [bx],al
mov al,[5+bx]
or al,00100000B
mov [5+bx],al ;可以将[5+bx]写成5[bx]
inc bx
loop s
mov ax,4c00h
int 21h
codesg ends

end start

-----
c语言描述上面的语句
char a[5] = "BaSiC";
char b[5] = "MinIX";
main()
{
int i;
i=0;
do{
a[i]=a[i]&0xDF;
B[i]=b[i]&0x20;
i++
}
while(i<5)
}
------------
7.SI和DI
si和di是8086CPU中和bx功能相近的寄存器,si和di不能够分成两个8位寄存器来使用。
mov bx,0
mov ax,[bx]
mov si,0
mov ax,[si]
mov di,0
mov ax,[di]
---
assume cs:codesg,ds:datasg

datasg segment

db 'welcome to masm!'
db '................'
datasg ends

codesg segment

start: mov ax,datasg

mov ds,ax
mov si,0
mov di,16
mov cx,8
s: mov ax,[si]
mov [di],ax
add si,2
add di,2
loop s
mov ax,4c00h
int 21h
codesg ends
end start
------
代码优化:
codesg segment

start: mov ax,datasg

mov ds,ax
mov si,0
mov di,16
mov cx,8
s: mov ax,[si]
mov 16[si],ax ;[si+16]
add si,2
loop s
mov ax,4c00h
int 21h
codesg ends
end start
------------
8.[bx+si]和[bx+di]
[bx+si]表示一个内存单元,bx的数值加上si的数值,表示偏移地址。[bx+si]可以写成[bx][si]
-----------------
9.[bx+si+idata]
表示一个内存单元,bx的数值加上si的数值再加上idata
----------------
10.不同的寻址方式的灵活应用
1)、[idata]用一个常量来表示地址,可用于直接定位一个内存单元。
2)、[bx]用一个变量来表示内存地址,可用于间接定位一个内存单元。
3)、[bx+idata]用一个变量和常量表示地址,可在一个起始地址基础上用变量间接定位一个内存单元。
4)、[bx+si]用两个变量表示地址
5)、[bx+si+idata]用两个变量和一个常量表示地址。
-----------
程序:将小写转换大写,进行了二次循环,cx只能存放循环次数,这里有两个循环,需要两个cx,而寄存器cx只有一个。解决办法将其中一个cx内存存放在栈中,等要用到,从栈中取出。释放内存,不需要占用内存。
assume cs:codesg,ds:datasg,ss:stacksg

datasg segment

db 'ibm '
db 'dec '
db 'dos '
db 'vax '
datasg ends

stacksg segment

dw 0,0,0,0,0,0,0,0
stacksg ends

codesg segment

start: mov ax,stacksg

mov ss,ax
mov sp,16
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s0: push cx
mov si,0
mov cx,3

s: mov al,[bx+si]

and al,11011111b
mov [bx+si],al
inc si
loop s
add bx,16
pop cx ;将原先存放在栈中的cx值,取出,放回寄存器cx中。
loop s0
mov ax,4c00h
int 21h
codesg ends
end start

转载于:https://www.cnblogs.com/lazyli/p/10946891.html

你可能感兴趣的文章
实现MyLinkedList类深入理解LinkedList
查看>>
自定义返回模型
查看>>
C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 客户端多网络支持
查看>>
HDU 4122
查看>>
Suite3.4.7和Keil u3自带fx2.h、fx2regs.h文件的异同
查看>>
打飞机游戏【来源于Crossin的编程教室 http://chuansong.me/account/crossincode 】
查看>>
[LeetCode] Merge Intervals
查看>>
【翻译自mos文章】当点击完 finishbutton后,dbca 或者dbua hang住
查看>>
Linux编程简介——gcc
查看>>
2019年春季学期第四周作业
查看>>
MVC4.0 利用IActionFilter实现简单的后台操作日志功能
查看>>
rotate the clock
查看>>
bugku 变量
查看>>
Python 环境傻瓜式搭建 :Anaconda概述
查看>>
数据库01 /Mysql初识以及基本命令操作
查看>>
数据库02 /MySQL基础数据类型以及多表之间建立联系
查看>>
Python并发编程04/多线程
查看>>
CF461B Appleman and Tree
查看>>
CF219D Choosing Capital for Treeland
查看>>
杂七杂八的小笔记本
查看>>