第六章
dw是定义字型数据,define word的缩写---assume cs:codecode segmentstart: 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 21hcode endsend start----------0123h,0456h,0789h,0abch....这些数据是存放在哪里的。是存放在当前代码段中,段地址:偏移地址,是cs:[0]开始;可以用debug加载程序,利用d命令查看内存情况-----------------将内存的数据放入栈中;需要定义栈的段地址,栈顶的位置,这里的栈顶的位置是30h,[0]-[15]存放着内存数据,栈空间是从[16]-[31]也就是20h-2fh,栈顶就是2fh+1也就是30h位置;assume cs:codesgcodesg 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,0start: mov ax,cs mov ss,ax mov sp,30h注释:程序中的数据是存放在代码段中的,所以,cs是段地址,也就是栈空间的段地址,栈顶的位置是30h; mov bx,0 mov cx,8s: push cs:[bx] add bx,2 loop s注:利用循环将,前16个字节的数据放入到栈中 mov bx,0 mov cx,8s0: pop cs:[bx] add bx,2 loop s0注:依次从栈中将数据取出,存放在[0]-[15]单元中 mov ax,4c00h int 21hcodesg endsend start--------------------3、将数据、代码、栈放入不同的段中定义不同的段,代码段为code,数据段为data,栈端为stackassume cs:code,ds:data,ss:stackdata segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdata endsstack segment
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0stack endscode segment
start: mov ax,stack mov ss,ax mov sp,20h mov ax,data mov ds,ax mov bx,0 mov cx,8s: push [bx] add bx,2 loop s mov bx,0 mov cx,8s0: pop [bx] add bx,2 loop so mov ax,4c00h int 21 hcode endsend start--------------第七章更灵活的定位内存地址的方法1、and和or指令and的指令是与,按位进行运算,全部为1,才是1,否则为0;如:0110与1010,结果是0010;mov al,01100011Band al,00111011B执行结果:al=00100011Bor的指令是或,只要一个值是1,那么就是1,两个都是0才是0;mov al,01100011Bor al,00111011B执行后,al=01111011B----2、关于ASCII码比如单词"desk"存储在计算机里的信息是二进制,,而计算机要将这些存储的信息再显示给我们看,就要对其进行解码。按一下键盘'a'时,计算机会经过的流程:按下a键,这个按键的信息被送入计算机,计算机用ASCII码规则对其进行编码,将其转化为61H存储在内存的指定空间中;文本编辑软件从内存中取出61H,将其送到显卡上的显存中;工作在文本模式下的显卡,用ASCII码的规则解释显存中的内存,61h被当做字符'a',显卡驱动显示器,将字符'a'的图像画在屏幕上。----------------3、以字符形式给出的数据在汇编程序汇总,用'....'的方式指明数据是以字符的形式给出的。assume cs:code,ds:datadata segment
db 'unIX' db 'foRK'data endscode segment
start: mov al,'a' mov bl,'b' mov ax,4c00h int 21hcode endsend startr命令后,查看到寄存器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:datasgdatasg segment
db 'BaSiC' db 'iNfOrMaTiOn'datasg endscodesg segment
start: mov ax,datasg mov ds,ax mov bx,0 mov cx,5s: mov al,[bx] and al,11011111B mov [bx],al inc bx loop s mov bx,5 mov cx,11s0: mov al,[bx] or al,00100000B mov [bx],al inc bx loop s0 mov ax,4c00h int 21hcodesg endsend start--------字母大小写转换;通过ASCII码:大写 十六进制 二进制A 41 01000001B 42 01000010..................小写 十六进制 二进制a 61 01100001b 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:datasgdatasg segment
db 'Basic' db 'MinIX'datasg endscodesg segment
start: mov ax,datasg
mov ds,ax mov bx,0 mov cx,5s: 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 21hcodesg endsend 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和DIsi和di是8086CPU中和bx功能相近的寄存器,si和di不能够分成两个8位寄存器来使用。mov bx,0mov ax,[bx]mov si,0mov ax,[si]mov di,0mov ax,[di]---assume cs:codesg,ds:datasgdatasg segment
db 'welcome to masm!' db '................'datasg endscodesg segment
start: mov ax,datasg
mov ds,ax mov si,0 mov di,16 mov cx,8s: mov ax,[si] mov [di],ax add si,2 add di,2 loop s mov ax,4c00h int 21hcodesg endsend start------代码优化:codesg segmentstart: mov ax,datasg
mov ds,ax mov si,0 mov di,16 mov cx,8s: mov ax,[si] mov 16[si],ax ;[si+16] add si,2 loop s mov ax,4c00h int 21hcodesg endsend 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:stacksgdatasg segment
db 'ibm ' db 'dec ' db 'dos ' db 'vax 'datasg endsstacksg segment
dw 0,0,0,0,0,0,0,0stacksg endscodesg segment
start: mov ax,stacksg
mov ss,ax mov sp,16 mov ax,datasg mov ds,ax mov bx,0 mov cx,4s0: push cx mov si,0 mov cx,3s: 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 21hcodesg endsend start