王爽的8086CPU王爽写的汇编语言言

8086汇编学习小记-王爽汇编语言实验16 - 左岸阳光 - 博客园
编写int 7ch中断例程,实现:
设置前景色
设置背景色
向前滚动一行
要求ah寄存器传递功能号:0, 1, 2, 3对应上述功能;al传递颜色值,al-&[0, 7].
中断程序中的call,jmp都应该选择偏移类型的指令,因为标号地址是编译器在汇编或者连接时期计算的,用偏移量才能保证指令安装在别的地址也能正常运行。
标号后无冒号只能出现在代码段,无冒号可以代表数据类型和地址,有冒号的标号只能代表偏移。
1 ;中断时的入栈顺序是pushf,push cs, push ip
2 assume cs : codesg, ss : stacksg
4 stacksg SEGMENT
dw 16 dup (0)
6 stacksg ENDS
10 codesg SEGMENT
mov es, ax
mov di, 0200h
mov ax, codesg
mov ds, ax
mov si, offset screen
mov cx, offset scend - offset screen
mov word ptr es : [7ch * 4], 0200h
mov word ptr es : [7ch * 4 + 2], 0
mov ax, 4c00h
30 screen:
jmp short begin
table dw f0 - screen + 200h, f1 - screen + 200h, f2 - screen + 200h, f3 - screen + 200h
mov ds, bx
mov bl, ah
add bx, bx
call word ptr [table + bx - screen + 200h]
mov bx, 0b800h
mov es, bx
mov cx, 2000
mov byte ptr es : [bx], ' '
mov bx, 0b800h
mov es, bx
mov cx, 2000
and byte ptr es : [bx + 1], b
or es : [bx + 1], al
shl al, cl
mov bx, 0b800h
mov es, bx
mov cx, 2000
and byte ptr es : [bx + 1], b
or es : [bx + 1], al
mov di, 0b800h
mov es, di
mov ds, di
mov si, 160
mov cx, 2000 - 80
mov di, 1920
mov cx, 80
mov byte ptr es : [di], ' '
118 scend:
119 codesg ENDS
120 END start汇编学习--常用寄存器功能介绍(基于8086CPU) - sd的专栏 - CSDN博客
汇编学习--常用寄存器功能介绍(基于8086CPU)
8086CPU常用的寄存器有AX,BX,CX,DX,DS,CS,ES,SS,IP,SP,SI,DI等。通过学习王爽老师主编的《汇编语言》(第二版)的4-7章,基本上对这些寄存器的使用有了一定的了解,现将这些寄存器的使用总结如下:
在汇编中使用描述符reg来表示一个寄存器,包括ax,bx,cx,dx,ah,al,bh,bl,ch,cl,dh,dl,sp,bp,si,di
使用描述符sreg表示一个段寄存器,包括ds,cs,ss,es
-----------------------AX,BX,CX,DX,BP,SI,DI---------------------
AX,BX,CX,DX是四个通用寄存器,大小为1个字(两个字节),可以直接读取一个字的内容到这些寄存器中,也可以按字节的方式读取这些寄存器。
以AX为例,如果想要读取AX低位字节的内容,使用AL(A low),想要读取AX高位字节的内容,使用AH(A high)。
如果将1234H存入到AX中,使用mov ax,1234H。这里需要注意的是,34保存在低位,12保存在高位。如果将AX存入到DS中,查看DS内容时,会发现34在前,12在后。因为DS是从低位显示到高位的。
到目前为止,使用AX最多的是将一个内存中的值赋给AX,然后通过AX将内存中的值存入不同的段中(CS,DS,SS,ES等)。因为对这些段的赋值,8086CPU不允许通过内存直接赋值,只能通过一个变量寄存器来间接赋值。
DX的使用和AX类似,有区别的是BX和CX。
BX通常存放的数据用来表示的是数据段DS的偏移地址。如mov ax,[bx]默认的是将ds*16 + bx所表示的物理内存中的数据传递给ax。
CX在程序刚加载的时候,存放的是程序的长度。另外,在使用循环LOOP时,通常是将循环的次数存放在CX中(插一句,如果是多层循环的话,就要考虑使用stack来push和pop来不断的存取CX值,可能这也是stack结构最初的使用吧。现在想想,确实是个很不错的设计)。
DP存放的是段SS的偏移地址。
SI,DI 可以单独使用,若想组合使用只能和BX或者BP组合来使用,如[bx + si],[bp + di]等
----------------------DS,CS,SS,ES段--------------------------
DS存放的是程序在内存中的起始段的段地址。这个段内的前256个字节(100H)存放的是PSP内容(不懂,只了解是存放程序和DOS通信的内容),之后才是程序的第一条指令的地址。而CS:IP指向的是程序执行指令的地址,起始地址为CS:0000。故有DS + 10H = CS。
如上,CS存放的是程序的实际执行指令的段地址,IP存放的是当前执行指令的偏移地址。在debug调试状态下,可以通过使用-g cs:IP来控制程序具体执行到哪一行指令处。
SS和SP结合使用,SS存放的是栈Stack的段地址,SP存放的是栈顶位置的偏移地址。栈的介绍在
ES(尚未学习到,后续补充)
在一个程序中,通常将数据,代码和栈放在不同的段中。数据存放在DS段中,代码存放在CS中,栈存放在SS中。如下程序所示:
assume cs:code, ds:data, ss:stack
data segment
dw h,0789h,0abch,0defh,0fedh,0cbah,0987h
stack segment
dw 0,0,0,0,0,0,0,0
stack ends
code segment
start: mov ax,stack
mov sp,16H
mov ax,data
push ds:[0]
push ds:[2]
pop ds:[0]
pop ds:[2]
mov ax,4c00h
-----------------------SI,DI-------------------------
SI和DI是和BX类似的两个寄存器,可以用来表示数据段的偏移地址。但是和BX不同的是,SI和DI不能拆分成两个8位寄存器来使用。
基于上面的解释,顺带把自己第七章7.9题的代码放上,作为理解使用:
assume cs:code,ds:data,ss:stack
data segment
db '1. display & & &'
db '2. brows & & & &'
db '3. replace & & &'
db '4. modify & & & '
stack segment
dw 0,0,0,0,0,0,0,0
stack ends
code segment
mov ax,data
mov ax,stack
mov al,[bx + si + 3]
mov [bx + si + 3],al
mov ax,4c00h
我的热门文章
即使是一小步也想与你分享汇编语言(8)

1&寄存器bp&bx&si&di
1)在8086CPU中,只有4个寄存器可以用来进行内存单元的寻址:bx&bp&si&di。
mov&ax,[bx]
mov&ax,[bx+si]
mov&ax,[bx+di]
mov&ax,[bp]
mov&ax.[bp+si]
mov&ax,[bp+di]
但不可以mov&ax,[bx+bp]或者&mov&ax,[si+di]
2)&使用bp寄存器时,指令中没有显性地指出段地址,段地址默认存储在ss中。
&&&mov&ax,[bp]&ax=((ss*16)+bp)
2&机器指令处理的数据在什么地方
&&&&CPU指令在执行前一刻,关心将要处理的数据所在的位置。指令在执行前,所要处理的数据在:CPU内部寄存器、内存、端口。
3&汇编语言中数据位置的表达
汇编语言中用3个概念来表达数据位置:立即数,寄存器,段地址+偏移地址
1)对于直接包含在机器指令中的数据(执行前在CPU的指令缓冲器中),称为立即数
例如:mov&ax,1&&add&bx,2000h
2)指令要处理的数据在寄存器中
例如:mov&ax,bx
3)指令要处理的数据在内存中,在汇编指令中可用[X]的格式给出偏移地址,段地址在某个段地址寄存器中,可显式给出或隐式给出。
mov&ax,[bp+si+8]
mov&ax,es:[bx]
4&寻址方式
当数据存放在内存中的时候,给定内存单元地址的方式成为寻址方式。
常用格式举例
EA=(idata)&SA=(ds)
EA=(bx)&SA=(ds)
寄存器寻址
EA=(bp)&SA=(ds)
EA=(si)&SA=(ds)
EA=(di)&SA=(ds)
[bx+idata]
EA=(bx+idata),SA=(ds)
寄存器相对寻址
用于结构体[bx].idata
用于数组&idata[si]&idata[bx]
&用于二位数组[bp][idata]
[bp+idata]
EA=(bp+idata),SA=(ss)
[si+idata]
EA=(si+idata),SA=(ds)
[di+idata]
EA=(di+idata),SA=(ds)
[bx+si]
EA=(bx+si),SA=(ds)
基址变址寻址
用于二位数组[bx][si]
[bx+di]
EA=(bx+di),SA=(ds)
[bp+si]
EA=(bp+si),SA=(ss)
[bp+di]
EA=(bp+di),SA=(ss)
[bx+si+idata]
EA=(bx+si+idata),SA=(ds)
相对基址变址寻址
用于表格结构中的数组
[bx+di+idata]
EA=(bx+di+idata),SA=(ds)
[bx].idata[si]
[bp+si+data]
EA=(bp+si+idata),SA=(ss)
用于二位数组
[bp+di+data]
EA=(bp+di+idata),SA=(ss)
Idata[bx][si]
注意:寄存器bp的默认段地址寄存器:ss
5&指令要处理的数据有多长
8086可以处理两张尺寸数据:byte和word。
在机器指令中要致命进行的是字操作还是字节操作。
1)&通过寄存器名指明要处理的数据的尺寸。&mov&ax,.bx&字操作&mov&al,1&字节操作
2)&在没有寄存器名存在的情况下,用操作符word&ptr或者byte&ptr&指明是字操作还是字节操作。
mov&word&ptr&ds:[0],1&字操作&
mov&byte&ptr&ds:[bx],4&&字节操作
-除数:8位/16位,存放在寄存器或内存中;
被除数:ax或者dx:ax中(16位或32位)&
若除数:8位,AL=商,AH=余数&被除数=16位
若除数:16位,AX=商,DX=余数&被输出=32位
格式:div&reg/内存单元
例如:div&byte&ptr&es:[0]&含义:al&=(ax)/(es*16+0)&的商&ah&=(ax)/(es*16+0)的余数
&&&&&&div&word&ptr&ds:[0]&含义:ax=(dx*10000h+ax)/(ds*16+0)的商
&&&&&&&&&&&&&&&&&&&&&&&&&&&&dx=(dx*10000h+ax)/(ds*16+0)的余数
7&伪指令&dd
dd&用于定义dword(double&word)双字
注:内存中是以字节空间编号,起始编号:0。参见第三章寄存器(内存访问)学习笔记。
8&操作符dup
db&重复的次数&dup&(重复的字节型数据)
dw&重复的次数&dup&(重复的字型数据)
dd&重复的次数&dup&(重复的双字型数据)
stack&segment
&&&db&200&dup&(0)
stack&ends
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1967次
排名:千里之外

我要回帖

更多关于 汇编语言 王爽 的文章

 

随机推荐