汇编语言调试几个常用指令
d:查看内存中的值
e:
u:翻译成汇编指令
t:执行
a:以汇编指令的格式再内存中写入一条机器指令
第4章 第一个程序(这章挺重要的)
4.2源程序
assume cs:codesg
codesg segment
mov ax 0123H
mov bx,0456H
add ax,bx
add ax,ax
mov ax,4c00H
int 21H
codesg ends
end
解释:1、汇编语言源程序包括汇编指令和伪指令
2、xxx segment ..........xxx ends 是成对的伪指令,定义了一个段
3、end 汇编程序结束符
4、assmue 将这个段和对应的段寄存器联系起来
5、程序的返回代码
4.3 编辑源程序edit命令
4.4 编译
masm.exe 1.asm
4.5 链接
link.exe 1.obj
4.9 debug程序执行跟踪
1、为了观察程序的执行过程,可以使用Debug.Debug可以将程序加载到内存,设置CS:IP指向程序的入口;
2、debug程序时:CS:IP指向程序的入口(也就是第一条指令的地方)而不是源程序的入口(重要)
3、可执行文件载入内存后,cx寄存器存放了程序的长度,即机器码共有15个字节(重要)
4、加载后,ds中存放着程序所在内存区的段地址,偏移地址为0;ds+10就是整个源程序的地址(重要)
5、ds和cs相差0010(256字节),创建一个程序段前缀256字节PSP
第五章 [bx]和[loop]
5.1 bx中存放的数据作为偏移地址EA,段地址SA默认再ds中;所以在使用bx时应该先初始化ds的值
mov ax,2000h
moc ds,ax
mov ax,[bx]
5.2 loop指令
1、执行loop s时,1.(cx)=(cx)-1; 2.判断cx值,不为0则跳到s标识处
2、使用框架
mov cx,循环次数
s:
循环执行的代码
loop s
编程用加法算123*236
assume cs:code
code segment
mov ax,0
mov cx,236
s:add ax,123
loop s
mov ax,4c00h
int 21h
code ends
end
5.3 Debug中跟踪loop
计算ffff:0006单元中的数乘3,结果放在dx中
(1)单元只有8位,结果放在16位寄存器中,不会越界
(2) mov al,[6]
mov ah,0
s:add dx,ax 循环
5-3程序实现
assume cd:code
code segment
mov ax,0ffffh
mov ds,ax
mov bx,6
mov al,[bx]
mov ah,0
mov dx,0
mov cx,3
s:add dx,ax
loop s
mov ax 4c00h
int 21h
code ends
end
5.5 loop和[bx]的联合使用
计算ffff:0~ffff:b单元中的数据的和,结果放在dx中
(1)结果会不会越界?8位累加放在16位寄存器不会越界
(2)直接累加不行,8位不能直接加到16位上,利用中间寄存器ax,ah=0;
5-5实现
assume cs:code
code segment
mov ax,0ffffh
mov ds,ax
mov dx,0
mov al,ds:[0]
mov ah, 0
add dx,ax
mov al,ds:[1]
mov ah, 0
add dx,ax
......
mov al,ds:[0bh]
mov ah, 0
add dx,ax
5-6改进后程序
mov cx,12
s:mov al,[bx]
mov ah,0
mov dx,ax
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
5-8将内存ffff:0单元数据复制到0:200~0:20b
(1)他们在不同的段,该怎么复制?每次循环重新设置ds
assume cs:code
code segment
mov bx,0
mov cx,12
s:mov ax,0ffffh
mov ds,ax
mov dl,[bx]
mov ax,0020
mov ds,ax
mov [bx],dl
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
5-9可以使用两个段寄存器来存放两个段地址ds=ffffh,es=0020h
assume cs:code
code segment
mov ax,0ffffh
mov ds,ax
mov ax,0020h
mov es,ax
mov bx,0
mov cx,12
s:mov dl,[bx]
mov es:[bx],dl
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
每条指令占用的字节数
第六章 包含多个段的程序
6.1 数据段
6-2 计算8个数据的和,保存在ax中
assume cs:code
code segment
dw 0123h,0333h,0678h,0324h,0343h,0333h.0acbh,0999h //定义字段,cs指向的16字节保存这数据
mov bx,0
mov ax,0
mov cx,8
s:add ax,cs:[bx] //如果不指定cs,系统会去读ds:[bx]中的值
add bx,2
loop s
mov ax,2c00h
int 21h
code ends
end
我们可以直接指定cs:ip到真正要执行的代码处:
assume cs:code
code segment
dw 0123h,0333h,0678h,0324h,0343h,0333h.0acbh,0999h //定义字段,cs指向的16字节保存这数据
start:mov bx,0 //这个start的作用就是把ip直接指向这里,但是前面的dw16字节依然在cs段内,用cs:[bx]依然可以引用
mov ax,0
mov cx,8
s:add ax,cs:[bx] //如果不指定cs,系统会去读ds:[bx]中的值
add bx,2
loop s
mov ax,2c00h
int 21h
code ends
end start 告诉程序入口在哪里
6.2 在代码段中使用栈(同理)
6-3将数据逆序存放
assume cs:code
code segment
dw 0123h,0333h,0678h,0324h,0343h,0333h.0acbh,0999h
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //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
//入栈
s0:pop cs:[bx]
add bx,2
loop s0
mov ax,4c00h
int 21h
code ends
end
6.3 将数据、代码、栈放入不同的段
6-4
assume cs:code, ds:data, ss:stack //将寄存器和段联系起来
data segment
dw 0123h,0333h,0678h,0324h,0343h,0333h.0acbh,0999h
data ends
stack segment
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack ends
code segment
start:mov ax,stack stack在这里等价16为地址例如1CD4
mov ss,ax //设置栈段的位置ss:sp
mov sp,20h
mov ax,data
mov ds,ax //设置数据段的位置ds,bx
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 s0
mov ax,4c00h
int 21h
code ends
end
注意:执行到ds赋值的时候就可以通过d ds:0来查看内存中的值了
第七章 更加灵活的定位内存地址的方法
7.1 and和or指令
mov al,01100011B
and al,00111011B
mov al,01100011B
or al,00111011B
7.3以字符形式给出的数据
7-1
assume cs:code, ds:data
data:segment
db 'unIX'
db 'foRX'
data ends
code:segment
start:move al,'a'
mov bl,'b'
code ends
end start
这个简单的汇编程序中;debug用r查看寄存器,ds指向整个源程序开始的地方1cc3,加上256字节(psp)后就是程序的起始处1cd3:0;
然后再加上‘unIX’‘foRX’占用一个段(16字节也就是8个字)0B3E
7.4大小写转换的问题
思路:某个字母可以用8位表示(128);例如a:97 A:65;相差32;只需要将第5位置1就位小写00100000
and al,11011111 把第五位置0
程序例题大小写问题
assume cs:codesg, ds:datasg
datasg segment
db 'BaSiC'
db 'iNdPrMAtiN'
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.10
s0:mov al,[bx]
or al,00100000B
mov al,[bx]
inc bx
loop s0
mov ax 4c00h
int 21h
codesg ends
end start
接下来几节主要就是讲如何定位内存单元的问题;新增si和di两个指令
7.5 [bx+idata]我们把idata具体化位200
意思就是表示一个内存单元,偏移地址(bx)+200;先看看bx里面的值再加上200
例如:mov ax,[bx+200]
等价于:mov 200[bx] == mov ax,bx.200
7.7 si和di寄存器
其实和bx寄存器相似,只是si和di不能够分成两个8位寄存器来使用
7.8 [bx+data]和[bx+di]
7.9 [bx+si+data]和[bx+di+idata]