网站建设方向市场分析,分销网站系统,最好网站建设公司哪家好,深圳建筑装饰人才网原视频
基础篇#xff1a;1.1编程环境的安装
打开DOSBox 0.74-3 Options.bat调整窗口大小
windowresolution1200x640
outputddrawmount c D:\masm
c:
debugDEBUG
用Debug的R命令查看、改变CPU寄存器的内容#xff1a; 用Debug的D命令查看内存中的内容#xff1a; 用Debu…原视频
基础篇1.1编程环境的安装
打开DOSBox 0.74-3 Options.bat调整窗口大小
windowresolution1200x640
outputddrawmount c D:\masm
c:
debugDEBUG
用Debug的R命令查看、改变CPU寄存器的内容 用Debug的D命令查看内存中的内容 用Debug的E命令改写内存中的内容 用Debug的U命令将内存中的机器指令翻译成汇编指令 用Debug的T命令执行一条机器指令 用Debug的A命令以汇编指令的格式在内存中写入一条机器指令。
mov,add,sub
mov ax,bx
axbx
add ax,bx
axbx
sub ax,bx
ax-bxmul,div,and,or
mul乘法指令
因下面要用到这里介绍一下mul指令mul是乘法指令使用mul做乘法的时候
注意以下两点。
(1)两个相乘的数两个相乘的数要么都是8位要么都是16位。如果是8位一个默认放在AL中另一个放在8位reg或内存字节单元中如果是16位一个默认在AX中另一个放在16位reg或内存字单元中。
(2)结果如果是8位乘法结果默认放在AX中如果是16位乘法结果高位默认在DX中存放低位在AX中放。mul bl
al*bl
结果在axmul bx
ax*bx
结果高位在DX 低位在AXdiv除法指令
(I)除数有8位和16位两种在一个reg或内存单元中。
(2)被除数默认放在AX或DX和AX中如果除数为8位被除数则为16位
默认在AX中存放如果除数为16位被除数则为32位在DX和AX中存放DX存放高16位AX存放低16位。
(3)结果如果除数为8位则AL存储除法操作的商AH存储除法操作的余数
如果除数为16位则AX存储除法操作的商DX存储除法操作的余数。div bl
ax/bl
结果ah为余数 al为商div bx
(dx*2^32ax)/bx
结果dx为余数 ax为商and or
(I)and指令逻辑与指令按位进行与运算。
例如指令
mov al,01100011B
and al,00111011B
执行后al00100011B
(2)or指令逻辑或指令按位进行或运算。
例如指令
mov al,01100011B
or al,00111011B
执行后al01111011Bshl
是逻辑左移指令它的功能为
(1)将一个寄存器或内存单元中的数据向左移位
(2)将最后移出的一位写入CF中
(3)最低位用0补充。mov al,01001000b
shl al,1
执行后al10010000b cf0shr
是逻辑右移指令它和shl所进行的操作刚好相皮
(1)将一个寄存器或内存单元中的数据向右移位
(2)将最后移出的一位写入CF中
(3)最高位用0补充。shr是逻辑右移指令它和shl所进行的操作刚好相反mov al,10000001b
shr al,1
执行后(al)01000000b,CF1dec inc neg xchg
dec ax
ax--
inc ax
ax
neg ax
ax取反
xchg ax,bx
ax与bx的值交换int int指令是X86汇编语言中最重要的指令之一。它的作用是引发中断调用“中断例程”interrupt routine。本文将介绍int指令的基本原理和应用以及BIOS和DOS系统的中断例程。一、int指令的原理1指令原型
int n
注
1n 表示中断号也可以称为中断类型码。n是一个字节大小的正整数范围为“0 - 255”。
2执行“int n”时CPU从中断向量表中找到第n号表项修改CS和IP(IP)(n*4)(CS)(n*42)3对8086PC中断向量表指定放在内存地址0处地址固定共1024个字节。每个表项占两个字低字存放偏移地址高字存放段地址。ds寄存器,段地址,偏移地址,物理地址
ds用来放段地址
存放当前正在运行的程序代码所在段的段基值
073f:0100
段地址为073f
偏移地址为0100
物理地址为073f*160100给ds寄存器赋值
mov ax,0100
mov ds,axcs:ip
基地址偏移地址
cs 为代码段寄存器一般用于存放代码
通常和IP 使用用于处理下一条执行的代码jmp
jmp bx
将ip寄存器的值改为bxss-sp pop push
存储栈的地址
ss-sp指向栈顶
push寄存器
:将一个寄存器中的数据入栈
pop寄存器
:出栈用一个寄存器接收出栈的数据-a
073F:0100 mova×,1234
073F:0103 push a×
073F:0104 mov b×,5678
073F:0107 push bx
073F:0108 pop ax
073F:0109 pop bx
073F:010Asp00fd
sp00fb
sp00f9073F:0100 78 56 34 12 00 00 00bp si di
mov ax,[bx]
mov ax,[si]
mov ax,[si1]
mov ax,[sibx]
错误指令
mov ax,[bxbp]
mov ax,[sidi]存放段地址的寄存器可以是默认的比如
mov ax,[0]
mov ax,[di]
mova,[bx8]
mowa%,[bxsi]
mov ax,[bxsiB]
等指令段地址默认在ds中
mov ax,[bp]
mov ax,[bp8]
mov ax,[bpsi]
mov ax,[bpsi8]
等指令段地址默认在ss中。(3)只要在[...]中使用寄存器bp,而指令中没有显性地给出段地址段地址就默认在ss中。es 为扩展段寄存器 ss 为栈段寄存器一般作为栈使用 和sp搭档
es 为扩展段寄存器
flag寄存器
标志truefalseName(名称)命题OFOV (Overflow)NV (Not Overflow)0verflowFlag(是否溢出)存在溢出SFNG(NeGative负的)PL(Plus正的)Sign Flag(结果的符号是正还是负)是负数正数看做无符号ZFZR(Zero)NZ(Not Zero)Zero Flag(运算结果是否为0)是0PFPE(Even偶数)Po(odd奇数)Parity Flag(结果中二进制位个数的奇偶性)是偶数个1CFCY(Carry yes)NC(Not carry)Carry Flag(进位标志)有进位DFDN (Down)UP(Up)Direction Flag(方向标志)si、di递减
adc
adc ax,bx
axaxbxCFsbb
sbb ax,bx
axax-bx-CFcmp
cmp是比较指令cmp的功能相当于减法指令只是不保存结果。cmp指令执行后将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。
cmp ax,bx
ax-bx如果(ax)(bx)则(ax)-(bx)0,所以zf1
如果(ax)≠(bx)则(ax)-(bx)≠0所以zf0
如果(ax)bx)则(ax)-(bx)将产生借位所以cfl
如果(ax)≥(bx)则(ax)-(bx)不必借位所以cf0
如果(ax)(bx)则(ax)-(bx)既不必借位结果又不为0所以cf0并且zf0
如果(ax)≤(bx)则(ax)-(bx)既可能借位结果可能为0所以cf1或zf1指令含义检测的相关标志位je等于则转移zf1jb低于则转移cf1ja高于则转移cf0且zf0
cmp ax,bx
je 073f:0106运行asm文件
masm
输入文件名
link 文件名
debug 文件名.asm循环语句loop
loop指令的格式是loop标号CPU执行loop指令的时候要进行两步操作
①cxcx-1:②判断cx中的值不为零则转至标号处执行程序如果为零则向下执行。
下面例子中ax2^12assume cs:code
code segmentstart:mov ax,2mov cx,12s:add ax,axloop sint 21H
code ends
end startcall ret
call在执行时会先将下一条指令所对应的ip地址入栈然后修改ip的值实现跳转, ret指令执行的时候将ip地址pop出来进行跳转call s ;
标号里面存放的是ip偏移地址 如果写成call 3H
那么意思就是跳转到CS:0003h这个位置
执行函数sassume cs:code
code segmentstart:mov ax,2mov cx,12call sint 21Hs:add ax,axloop sret
code ends
end startcall Far ptr retf
ret和call配套使用retf和call Far ptr 配套使用
可以通过标号(函数名称)之间数值相减计算函数体代码所占用的内存空间大小
retf需要配合栈进行使用当程序执行到retf这条指令时会连续从栈中pop两次数据第一次的数据赋值给CS第二次的数据赋值给IP那么如果我们想要跳转到指定的指令需要将该指令的段地址和偏移地址分别push进栈中
stack segmentdb 128 dup(0)
stack endscode segmentstart:mov ax,stackmov ss,axmov sp,128mov ax,0710H ;指定段地址push axmov ax,0003H ;指定偏移地址push axretf ;程序跳转到0710:0003H这个位置
code ends
end start
内存地址 机器码 汇编指令
1000:0 b8 00 00 mov ax,0
1000:3 9a 09 00 00 10 call far ptr s
1000:8 40 inc ax
1000:9 58 s:pop axadd ax,axpop bxadd ax,bx为什么ax会是1010?详细解答执行指令先要读入到指令缓冲区中
读进去以后IP已经指向下一条指令了
call far ptr执行了push cs,push ip,jmp far ptr
这么指行的话call far ptr s的cs:1000,ip:8
把cs先扔进栈后扔ip
那么到了s:pop ax这个时候应该是ip先出来所以ax8
接着执行add ax,ax6
接着pop bx,现在bx1000
然后执行add ax,bx
那么就是ax1010H代码段、数据段、栈段、dup指令
assume cs:codesg,ds:data,ss:stack
MASM内部以数基的个数定义了多种数据类型
BYTE,db,8位
WORD,dw,16位
DWORD,dd,32位
QWORD,dq,64位db 10 dup (0)
初始化10个值为0的空间assume cs:codesg,ds:data,ss:stack
data segmentdw 123H,456H,789H,OabcH,OdefHdb 3 dup(1,2,3)db 3 dup (abc,def)
data ends
stack segmentdb 10 dup (0)
stack ends
codesg segmentstart:dw hellow roldmov ax,3mov cx,11call sinc bxinc bxint 21Hadd ax,axloop s
codesg ends
end startoffset
操作符offset在汇编语言中是由编译器处理的符号它的功能是取得标号的偏移地址。比如下面的程序
assume cs:codesg
codesg segmentstart:mov ax,offset start;相当于mov ax,0s:mov ax,offset s;相当于mov ax,3
codesg ends
end startjmp short s jmp far s
跳转到s位置
jmp short s
机器码显示距离
jmp far s
机器码显示距离地址jmp dword ptr
功能从内存单元地址处开始存放着两个字高地址处的字是转移的目的段地址低地址处是转移的目的偏移地址。
内存单元地址可用寻址方式的任一格式给出。
比如下面的指令
mov ax,0123H
mov ds:[0],ax
mov word ptr ds:[2],0
jmp dword ptr ds:[0]数组
data1 dd 0, 1, 2, 4 ;
相当于 int data1[] { 0, 1, 2, 3 };
data1[1]是内存地址1(不论什么类型都是1个字节)lea
lea是“load effective address”的缩写
简单的说lea指令可以用来将一个内存地址直接赋给目的操作数
例如lea eax,[ebx8]就是将ebx8这个值直接赋给eax而不是把ebx8处的内存地址里的数据赋给eax。
而mov指令则恰恰相反例如mov eax,[ebx8]则是把内存地址为ebx8处的数据赋给eax。5.11输出hello world
assume cs:codesg,ds:data,ss:stack
data segmeNTstr db hello world,$
data ends
stack segmentdb 10 dup (0)
stack ends
codesg SEgmentstart: mov ax,datamov ds,axlea dx,str mov ah,9int 21Hmov ah,4cHint 21H
codesg ends
end start
5.12字符串转大写
assume cs:codesg,ds:data,ss:stack
data segmeNTstr db hello world,$
data ends
stack segmentdb 10 dup (0)
stack ends
codesg SEgmentstart: mov ax,datamov ds,axmov bx,0mov cx,11s:mov al,[bx]and al,1011111Bmov [bx],alinc bxloop s;mov dx,offset strlea dx,str mov ah,9int 21Hmov ah,4cHint 21H
codesg ends
end start
5.13字符串转小写
assume cs:codesg,ds:data,ss:stack
data segmeNTstr db hello world,$
data ends
stack segmentdb 10 dup (0)
stack ends
codesg SEgmentstart: mov ax,datamov ds,axmov bx,0mov cx,11s:mov al,[bx]or al,0100000Bmov [bx],alinc bxloop s;mov dx,offset strlea dx,str mov ah,9int 21Hmov ah,4cHint 21H
codesg ends
end start
5.14求数组最小值
assume cs:codesg,ds:data,ss:stack
data segmeNTstr db hello world,$
data ends
stack segmentdb 10 dup (0)
stack ends
codesg SEgmentstart: mov ax,datamov ds,axmov bx,0mov cx,11mov ah,0FFHs:mov al,[bx]cmp ah,aljna s1mov ah,als1:mov [bx],alinc bxloop s;mov dx,offset strlea dx,str mov ah,9int 21Hmov ah,4cHint 21H
codesg ends
end start
5.15求数组最大值
assume cs:codesg,ds:data,ss:stack
data segmeNTstr db hello world,$
data ends
stack segmentdb 10 dup (0)
stack ends
codesg SEgmentstart: mov ax,datamov ds,axmov bx,0mov cx,11mov ah,0s:mov al,[bx]cmp ah,aljnb s1mov ah,als1:mov [bx],alinc bxloop s;mov dx,offset strlea dx,str mov ah,9int 21Hmov ah,4cHint 21H
codesg ends
end start
5.21数组求和
assume cs:code,ds:data,ss:stack
data segment arr db 1,2,3,4,10,20,30,40res db 8 dup (0)
data endsstack segment db 100 dup (0)
stack endscode segment start:mov ax,datamov ds,axmov bx,0mov cx,8for:add al,arr[bx]inc bxloop formov ax,4c00Hint 21
code ends
end start
5.22拷贝数组
assume cs:code,ds:data,ss:stack
data segment arr db 1,2,3,4,10,20,30,40res db 8 dup (0)
data endsstack segment db 100 dup (0)
stack endscode segment start:mov ax,datamov ds,axmov bx,0mov cx,8for:mov al,arr[bx]mov ds:res[bx],alinc bxloop formov ax,4c00Hint 21
code ends
end start
5.23用sidi翻转数组
assume cs:code,ds:data,ss:stack
data segment arr db 1,2,3,4,10,20,30,40res db 8 dup (0)
data endsstack segment db 100 dup (0)
stack endscode segment start:mov ax,datamov ds,axmov si,0mov di,7mov cx,8for:mov al,arr[si]mov ds:res[di],alinc sidec diloop formov ax,4c00Hint 21
code ends
end start
5.31用栈翻转数组
assume cs:code,ds:data,ss:stack
data segment arr dw 1111H,2222H,3333H,4444H,5555H,6666H,7777H,8888Hres db 800 dup (0)
data endsstack segment db 1000 dup (0)
stack endscode segment start:mov ax,datamov ds,axmov ax,stackmov ss,axmov sp,100mov bx,0mov cx,8for: push ds:arr[bx]add bx,2loop formov bx,0mov cx,8for1: pop ds:arr[bx]add bx,2loop for1mov ax,4c00Hint 21
code ends
end start
5.32动态规划求斐波那契数列
assume cs:code,ds:data,ss:stack
data segment arr dw 1H,1H,100 dup (0)res db 800 dup (0)
data endsstack segment db 100 dup (0)
stack endscode segment start:mov ax,datamov ds,axmov ax,stackmov ss,axmov bx,4mov cx,30for :mov dx,0add dx,ds:arr[bx-2]add dx,ds:arr[bx-4]mov ds:arr[bx],dxadd bx,2loop formov ax,4c00Hint 21
code ends
end start
5.41循环把二维矩阵某一列转大写
assume cs:codesg,ds:data,ss:stack
data segmeNTstr db aaaaabbbbbccccc db aaaaabbbbbccccc db aaaaabbbbbccccc db aaaaabbbbbccccc ,$data ends
stack segmentdb 10 dup (0)
stack ends
codesg SEgmentstart: mov ax,datamov ds,axmov bx,0mov cx,4for:mov al,ds:str[bx5]and al,11011111Bmov ds:str[bx5],aladd bx,16loop forlea dx,str mov ah,9int 21Hmov ah,4cHint 21H
codesg ends
end start
5.42二重循环把指定矩形转大写
assume cs:codesg,ds:data,ss:stack
data segmeNTstr db aaaaabbbbbccccc db aaaaabbbbbccccc db aaaaabbbbbccccc db aaaaabbbbbccccc ,$data ends
stack segmentdb 10 dup (0)
stack ends
codesg SEgmentstart: mov ax,datamov ds,axmov bx,0mov cx,4for:mov dx,cxmov si,0mov cx,5for1:mov al,ds:str[bxsi]and al,11011111Bmov ds:str[bxsi],alinc siloop for1mov cx,dxadd bx,16loop forlea dx,str mov ah,9int 21Hmov ah,4cHint 21H
codesg ends
end start
5.51冒泡排序
assume cs:codesg,ds:data,ss:stack
data segmeNTarr db 0A2H,24H,07H,3AH,1BH,0F1H,3BH,25H,81Hdata ends
stack segmentdb 10 dup (0)
stack ends
codesg SEgmentstart: mov ax,datamov ds,axmov bx,0mov cx,8for:mov dx,cxmov si,8mov cx,8sub cx,bxfor1:mov ah,ds:arr[si]mov al,ds:arr[si-1]cmp ah,aljnb allxchg ah,almov ds:arr[si],ahmov ds:arr[si-1],al all:dec siloop for1mov cx,dxadd bx,1loop formov ah,4cHint 21H
codesg ends
end start
5.61十进制转16进制
assume cs:codesg,ds:data,ss:stack
data segmeNTstr db 00012345,$
data ends
stack segmentdb 10 dup (0)
stack ends
codesg SEgmentstart: mov ax,datamov ds,axmov bx,0mov cx,8mov ax,0s:mov dx,axshl ax,1shl ax,1 shl ax,1shl dx,1add ax,dx
;乘10add al,str[bx]adc ah,0sub ax,30H inc bx loop smov ah,4cHint 21H
codesg ends
end start
5.61十进制转16进制并输出
assume cs:codesg,ds:data,ss:stack
data segmeNTstr db 00002333,$res db 0000,$
data ends
stack segmentdb 100 dup (0)
stack ends
codesg SEgmentstart: mov ax,datamov ds,axmov ax,stackmov ss,ax mov sp,10mov si,4mov bx,0mov cx,8mov ax,0s:mov dx,axshl ax,1shl ax,1 shl ax,1shl dx,1add ax,dx
;乘10add al,str[bx]adc ah,0sub ax,30H inc bx loop s;ax3039mov cx,4l:mov dx,axand dx,0FHadd dx,30Hcmp dx,3AHjb s1add dx,7H
;求出3039的ASCII码pushs1:dec simov ds:res[si],dlshr ax,1shr ax,1shr ax,1shr ax,1loop l;mov dx,offset reslea dx,resmov ah,9int 21Hmov ah,4cHint 21H
codesg ends
end start