编辑:vim/edit
编译:masm
链接:link
将内存2000:0,2000:1,2000:2,2000:3单元中的数据送入al,bl,cl,dl中
mov ax,2000
mov ds,ax;段地址2000h送入ds
mov bx,0;偏移地址0送入bx
mov al,[bx];ds:bx单元中的数据送入al
mov ax,2000
mov ds,ax;段地址2000h送入ds
mov al,ds:[0]
比较
mov al,[0];将常量0送入al中
mov al,ds:[0];(al)=((ds)*16+0)
mov al,ds:[bx];(al)=((ds)*16+(bx))
mov al,ds:[bx];与上面相同
循环
assume cs:code
code segment
mov ax,0ffffh
mov ds,ax;初始化ds:bx指向ffff:0
mov bx,0;初始化累加寄存器dx,(dx)=0
mov cx,12;初始化循环计数寄存器
s: mov al,[bx]
mov ah,0
add dx,ax;间接向dx中加上((ds)*16+(bx))的数值
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
复制
assume cs:code
code segment
mov bx,0;偏移位置从0开始
mov cx,12;循环12次
s: mov ax,0fffh
mov ds,ax;(ds)=0ffffh
mov dl,[bx];(dl)=((ds)*16+(bx)),将ffff:bx中的数据送入dl
mov ax,0020h
mov ds,ax;(ds)=0020h
mov [bx],dl;((ds)*16+bx)=(dl),将dl的数据送入0020:bx
inc bx;偏移位置加1
loop s
mov ax,4c00h
int 21h
code ends
end
代码段中使用栈
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;用dw定义16个字型数据,在程序加载后,将取得16个字的内存空间,存放16个数据,在后面的程序中将这段空间当作栈来使用
start: mov ax,cs
mov ss,ax
mov sp,30h
mov bx,0
mov cx,8
s:push cs:[bx]
add bx,2
loop s;将代码0-15单元中的8个字型数据依次入栈
mov bx,0
mov cx,8
s0:pop cs:[bx]
add bx,2
loop s0;出栈8个字型数据到代码段0-15单元
mov ax,4c00h
int 21h
codesg ends
end start;指明程序的入口在start处
初始状态下栈为空,所以ss:sp要指向栈底
将数据,代码,栈放入不同的段
QA:CPU如何知道stack放栈,data放数据?
mov ax,stack
mov ss,ax
mov sp,20h
设置ss指向stack,设置ss:sp指向stack:20
大小写转换问题
思路:大写ASCII码的第5位为0,小写字母的第5位为1
assume cs:codesg,ds:datasg
datasg segment
db 'Basic'
db 'iNfOrMaTiOn'
datasg ends
codesg segment
start:mov ax,datasg
mov ds,ax;设置ds指向daatsg
mov bx,0;设置(bx)=0,ds:bx指向‘Basic’的第一个字母
mov cx,5;设置循环次数5,因为‘Basic’有5个字母
s:mov al,[bx];将ASCII码从ds:bx所指向的单元中取出
and al,11011111B;将al中的ASCII码的第5位置为0,变为大写字母
mov [bx],al;将转变后的ASCII码写回原单元
inc bx
loop s
mov bx,5
mov cx,11
s0:mov al,[bx]
or al,00100000B;将第5位置变为1
mov [bx],al
inc bx
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
[bx]一个内存单元
[bx+idata]表示一个内存单元
下面三个指令相同
- mov ax,[bx+200]
- mov ax,200[bx]
- mov ax,[bx],200
下面两个指令相同
- mov ax,[bx+si]
- mov ax,[bx] [si]
(ax)=((ds)*16+(bx)+(si))
idata是常量,bx,si是变量
reg表示一个寄存器,sreg表示一个段寄存器
关注机器指令处理的数据在什么地方
mov bx,[0];内存,ds:0单元
mov bx,ax;CPU内部,ax寄存器
mov bx,1;CPU内部,指令缓存器
段地址(SA)和偏移地址(EA)
- mov ax,ds:[bp]
(ax)=(ds)*16+(bp)
SA=(ds),EA=(bp)
X ptr指明内存单元的长度,X再汇编指令中可以为word或byte
例如mov word ptr ds:[0],1 指明了指令访问的内存单元是一个字单元
db字节型 dw字型 dd双字型数据
如dd 100
dup重复
dw (重复次数) dump (数据)
如db 3 dup (0) ,即db 0,0,0
db 3 dup(0,1,2),即db 0,1,2,0,1,2,0,1,2
转移指令的原理
start:mov ax,0
mov bx,0
jmp short s
add ax,1
s:inc
REVIEW:1.从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲器;2.(IP)=(IP)+所读取指令长度,从而指向下一条指令;3.执行指令,转到1,重复过程
- CS= ,IP= CS:IP指向EB 03(jump short s的机器码)
- 读取指令码EB 03进入指令缓冲器
- IP=IP+所读取指令长度(2),指向add ax,1
- CPU执行指令缓冲器中的指令EB 03(重点,如果EB 03没有对IP修改的话,应该执行add ax,1)
- 执行后,IP=000BH,CS:IP指向inc ax
jmp word ptr 内存单元地址(段内转移)
jmp dword ptr 内存单元地址(段间转移)
jcxz相当于if((cx)==0)jump short 标号;
loop相当于(cx)–;if((cx)!=0)jump short 标号;
jump short s的转移范围是-128~127
offset
CPU执行ret指令,修改IP,pop IP
(IP)=((ss)*16+(sp))
(sp)=(sp)+2
CPU执行retf指令,修改CS和IP,POP IP,POP CS
(IP)=((ss)*16+(sp))
(sp)=(sp)+2
(IP)=((ss)*16+(sp))
(sp)=(sp)+2
CPU执行call指令,将CS和IP压入栈,转移,pump IP ;jmp near ptr标号
(sp)-=2
((ss)*16+(sp))=(IP)
IP+=16位位移
call far ptr 相当于push CS; push IP; jmp far ptr
mov ax,6;call ax将6存入ax,调用地址6处的函数
mul做乘法,要么都是16位要么都是8位
mul byte ptr ds:[0]
(ax)=(al)*((ds)*16+0)
ZF标志:零标志位。结果为0,ZF=1(逻辑为真),结果为1,ZF=0
PF标志:奇偶标志位,bit位个数是否为偶数
SF标志:符号标志位,非负,sf=1
CF标志:进位标志符,
cmp ax,bx即比较ax-bx
je等于则转移
jne
jb低于则转移below
jnb不低于则转移
ja高于则转移above
jna不高于则转移