汇编语言复习提纲
汇编语言复习提纲
考试时间:十六周周一
考试形式:笔试
考试范围:第一章-第九章
题型:填空、简答、程序设计
教材:IBM-PC汇编语言程序设计(第二版)
作者:@TheSilverMoon
博客:https://www.cnblogs.com/TheSilverMoon/
第一章
- 进制转换
- 补码加法、减法
- 与或非、异或运算
第二章
80×86寄存器组
- ax(accumulator),做为累加器用,在乘除等指令中指定用来存放操作数
- bx(base),可以做为通用寄存器,经常用做基址寄存器
- cx(count),可以做为通用寄存器,常用来保存计数值(比如在loop中)
- dx(data),可以做为通用寄存器,一般在双字长运算时把dx和ax组合在一起存放一个双字长数,dx存高位。
- sp(stack pointer)堆栈指针寄存器(指示段顶偏移地址)
- bp(base pointer)基址指针寄存器(堆栈区中的一个基地址)
- si(source index)源变址寄存器和di(destination index)目的变址寄存器一般与ds联用,用来确定数据段中某一存储单元的地址。串处理指令中,si和di做为隐含的源变址和目的变址寄存器。
- ip(instruction pointer)指令指针寄存器,用来存放代码段中的偏移地址
- flags 标志寄存器
条件码
- of(overflow)操作数超出了机器能表示的范围时为1
- sf(sign flag)记录运算结果的符号,负置1
- zf(zero flag)运算结果为0时,置1
- cf(carry flag)进位标志,进位置1
- af(auxiliary carry flag)记录第三位(半个字节)产生的进位值
- if(interrrupt flag)if为1时,CPU正常响应可屏蔽中断请求
80×86地址总线为20位 1m=2^20,当机器字长为16位时,大部分数据是以字为单位,存放时,低位字节放入低地址,高位字节放入高地址,如存放5678h,低位78h存放在0004h单元中,高位56h存放在0005h单元中
20位物理地址由16位段地址和16位偏移地址组成,段地址左移4位(16进制左移1位)再加上偏移地址即为物理地址。
第三章
80×86寻址方式
- 立即寻址方式
例:mov al(八位寄存器),5(源操作数) - 寄存器寻址方式 例:mov ax,bx 16位寄存器:ax,bx,cx,dx,si,di,sp,bp 8位寄存器:al,ah,bl,bh,cl,ch,dl,dh
- 直接寻址方式
例:mov ax(16位寄存器),[2000h](EA)
EA(Effective Address)=基址+(变址X比例因子)+位移量
加中括号表示偏移地址,默认在DS
可以使用段跨越前缀,如mov ax,ES:[2000h],但在某些情况下不可以使用段跨越前缀(书P39) - 寄存器间接寻址方式 例:mov ax,[bx] 若ds=2000h,bx=1000h 物理地址=20000+1000=21000h
- 寄存器相对寻址方式
move ax,count[si] count为16位位移量的符号地址 类似的,可以有mov eax,table[ESI]esi内容指向此表格中的一项
适用于字符串、数组、表格的处理 - 基址变址寻址方式 例:mov ax,[bx][di]或mov ax,[bx+di]
段内直接寻址:
指令格式为:
jmp near ptr progia
jmp short quest
如果位移量为16位,在符号地址前加near ptr操作符;如果为8位,在其之前加short
段内直接寻址:
jmp bx
80×86指令系统
数据传送指令:
mov 传送
movsx 带符号扩展传送
push 进栈
pop 出栈
xhcg 交换
lea 有效地址送寄存器
lea reg,src ;把源操作数的有效地址送到指定寄存器当中
类型转换指令:
cbw 字节转换成字
cwd 字转换为双字
- 执行的操作:al的内容符号扩展到ah,形成ax中的字。即如果al的最高有效位为0,则ah为0;如al的最高有效位为1,则ah=0ffffh
- 执行的操作:ax的内容符号扩展到dx,形成dx:ax中的双字
算数指令:
add 加法
adc 带进位加法
inc 加一
xadd 交换并相加
sub 减法
sbb 带借位减法
dec 减一
cmp 比较
mul 无符号乘法
imul 带符号乘法
div 除法
idiv 带符号除法
add dst,src
adc dst,src
adc dst.src
inc opr ;opr是操作数的意思
;除inc指令不影响cf外,其他都影响条件标志位
;of 可以用来表示带符号数的溢出,cf可以表示无符号数的溢出
sub dst,src
sbb dst,src
dec opr ;
cmp opr1,opr2;执行减法操作,但是不保存结果,只是根据结果设置条件标志位,后面往往跟着一条条件转移指令,根据结果产生不同的程序分支
mul src
;字节操组数: ax <- al * src 两个八位数相乘得到的十六位数,存在ax中
;字操作数: (dx.ax) <- ax * src 两个八位数相乘得到的十六位数,存在dx,ax中;dx存高位,ax存低位
div src ;16位被除数在ax中,8位除数为源操作数,结果的8位商在al中,8位余数在ah中
idiv src ;32位的被除数在dx,ax中,16位除数为源操作数,结果的16位在ax中,16位的余数在dx中
逻辑指令:
and 逻辑与
or 逻辑或
not 逻辑非
xor 异或
test 测试
and dst,src
or des,src
not opr
xor dst,src
test opr1,opr2 ;两个操作数想与,结果不保存,只根据其特征置条件码
;not 不允许使用立即数,其他的至少有个一个操作数必须存放在寄存器中
位移指令:
shl 逻辑左移
sal 算术左移
shr 逻辑右移 sar 算术右移
rol 循环左移
ror 循环右移
rcl 带进位左移
rcr 带进位右移
shl opr,cnt
sal opr,cnt
sar opr,cnt
rol opr,cnt
ror opr,cnt
rcl opr,cnt
rcr opr,cnt
如果大于cnt大于1,则需要存在cl中,cf保存移出的最后一位
串处理指令:
movs 串传送
cmps 串比较
ins 串输入
outs 串输出
rep 重复
repe 相等则重复
repne 不相等则重复
rep string primitive ;string primitive可为各种指令
movs dst,src
条件转移指令:
jz(jump if zero) 结果为0则转移
jnz(jump if not zero) 结果不为0则转移
js(jump if sign) 结果为负则转移 jns(jump if not sign) 结果为正则转移
jbe(jump if below or equal)低于或等于,或不高于则转移
jnbe(jump if not below or equal,or not above) 不低于或等于,或高于则转移
jge 不小于则转移 jng 不大于则转移
循环指令:
loop 循环
loopz 相等或为0时循环
loopnz 不相等或不为0时循环
子程序:
call 调用
ret 返回
call dst
ret
中断:
int中断指令
int type
第四章
伪操作
assume 伪操作
明确段和段寄存器的关系
例:
assume cs:code,ds:data,ss:stack
数据定义及存储器分配伪操作
- DB 定义字节,其后的每个操作数都占有一个字节(8位)
- DW 定义字,其后的每个操作数占有一个字(16位,低位字节在第一个字节地址中,高位字节在第二个字节地址中)
- DD 定义双字,其后的每个操作数占有两个字(32位)
data_byte db 10,4,10h
data_word dw 100,100h,-5
data_dw dd 3*20,0fffdh
- 操作数\’?\’可以保留存储空间,但不存入数据
abc db 0,?,?,0
- dup 复制操作符
array1 db 2 dup(0,1,2,?)
array2 db 100 dup(?)
- EQU 表达式赋值伪操作
constant equ 256
data equ height+12
alpha equ 7
beta equ alpha-2
addr equ var+beta
b equ [bp+8]
p8 equ ds:[bp+8]
地址计数器与对准伪操作
- \’$\’地址计数器
汇编程序使用地址计数器来保存当前正在汇编的指令的偏移地址。开始汇编或在每一段开始时,地址计数器初始化为0,之后每处理一条指令,地址计数器就增加一个值,此值为该指令所需要的字节数
例:
array dw 1,2,$+4,3,4,$+4
若汇编时array分配的偏移地址为0074,则存储区如下:
TIPS:$只代表该指令的首地址
数值回送操作符
- type
type expression
例:
array dw 123
add si,type array
该语句形成为:add si,2
**如果该表达式是变量,db回送1,dw回送2,dd回送4,如果该表达式为常量,回送0 **
- length
length variable
对于变量中使用dup的情况,回送分配给该变量的单元数,其他情况送1
- size
size variable
回送分配给该变量的字节数,此值是length和type的乘积
- offset
offset variable/label
回送变量或标号的偏移地址值
- seg
seg variable/label
回送变量或标号的段地址值
- high&low
const equ 0abcdh
mov ah,high const
将汇编成mov ah,0abh
上机过程(★)
mount d d:\masm
d:
masm filename
link filename
debug filename.exe / filename.exe
- 建立asm文件
- 用masm程序产生obj文件
- 用link程序产生exe文件
- 执行程序
常用命令:
- G命令:运行当前在内存中的程序
- D命令:显示一定范围内存地址的内容
格式:d [range]
如果键入以下命令,Debug 将从 CS:100 开始显示 20h 个字节的内容:
dcs:100 l 20
如果键入以下命令,Debug 将显示范围从CS 段的100h 到115h 中所有字节的内容:
dcs:100 115 - R命令:显示或改变一个或多个 CPU 寄存器的内容
r [register-name] - U命令:反汇编字节并显示相应的原语句,其中包括地址和字节值。反汇编代码看起来象已汇编文件的列表
u [range]
参数
如果在没有参数的情况下使用,则 u 命令分解 20h 字节(默认值),从前面 u 命令所显示地址后的第一个地址开始。
range
指定要反汇编代码的起始地址和结束地址,或起始地址和长度。
第五章
本章内容老师上课说以作业为主,下面放一下作业的代码
5.6 编写程序,将一个包含有20个数据的数组m分成两个数组:正数数组p和负数数组n,并分别把这两个数组中数据的个数求出来
data segment
count equ 20
array dw 20 dup(?);存放数组
count1 equ 0;正数个数
array1 dw 20 dup(?)
count2 equ 0;负数个数
array2 dw 20 dup(?)
data ends
code segment
main proc far
assume cs:code,ds:data
start:
push ds;设置返回dos
xor ax,ax
mov ax,data
mov ds,ax;给ds赋值
begin:
mov cx,count
lea bx,array
lea si,array1
lea di,array2
begin1:
mov ax,[bx]
cmp ax,0
js negative
mov [si],ax;是正数,存入数组
inc count1
add si,2
jmp next
negative:
mov [di],ax
inc count2
add di,2
next:
add bx,2
loop begin1
mov al,count1
call print
mov al,count2
call print
mov ah,4ch
int 21h
ret
main endp
print proc near
aam ;将(AL)中的二进制数转换为二个非压缩 BCD 码,AH←AL/10(商),AL←AL%10(余数)
add ah, ‘0’ ;变为 0~9 的 ASCII 码
mov dl, ah
mov ah, 2 ;显示一个字符的 DOS 调用
int 21H
add al, ‘0’ ;变为 0~9 的 ASCII 码
mov dl, al
mov ah, 2 ;显示一个字符的 DOS 调用
int 21h
ret
code ends
end start
5.7 试编制一个汇编语言程序,求出首地址为data的100d字数组中的最小偶数,并将其存在ax中
dsg segment
data dw 100 dup(?)
dsg ends
code segment
main proc far
assume cs:code,ds:dsg
start:
begin:
mov bx,0
mov cx,100
comp:
mov ax,data[bx]
add bx,2
test ax,01h ;判断是否是偶数
loopnz comp;loop not zero ,继续比较下一个
jnz stop
jcxz stop;若cx=0,则最后一个是偶数,即为最小偶数
comp1:
mov dx,data[bx]
add bx,2
test dx,01h
jnz next;不是,比较下一个数
cmp ax,dx ;ax<dx吗
jle next
mov ax,dx
next:loop comp1
stop:ret
main endp
code ends
end start
5.12 有一个首地址为MEM的100d字数组,试编制程序删除数组中所有为0的项,并将后续项向前压缩,最后将数组的剩余部分补上0
data segment
mem dw 100 dup(?)
data ends
code segment
main proc far
assume cs:code,ds:data
start:
push ds
xor ax,ax
push ax
mov ax,data
mov ds,ax
begin:
mov si,(100-1)*2;SI指向mem末元素的首地址
mov bx,-2 ;地址指针的初值
mov cx,100 ;count
comp:
add bx,2
cmp mem[bx],0
jz cons
loop comp
jmp finish;比较完了,无0结束
cons:
mov di,bx
cons1:
cmp di,si;到最后了吗
jae nomov
mov ax,mem[di+2];后面元素向前移
mov mem[di],ax
add di,2
jmp cons1
nomov:
mov [si],0;最后元素补0
loop comp
finish:
ret
main endp
code ends
end start
第六章
子程序
格式:
procedure_name proc attribute(near/far)
.
.
.
procedure_name endp
堆栈过程:
栈是一种先入后出的数据结构
pushf 的功能是将标志寄存器的值压栈
十进制转十六进制和十六进制转十进制
十进制转十六进制:
;_______________________________________________________________
code segment
assume cs:code
main proc far
call DecToBinary
call BinaryToHex
main endp
;_______________________________________________________________
DecToBinary proc near ;十进制转二进制
mov bx,0 ;清空bx
input:
mov ah,1
int 21h ;调用dos
sub al,30h ;转为二进制(通过ASCII)
jl exit ;如果小于0,退出
cmp al,9d ;如果大于9
jg exit ;直接退出
cbw ; 把字节转换成字。AL的内容符号扩展到AH,形成AX中的字
;当前数字在ax中
xchg ax,bx ;交换ax,bx中的数字,交换之后ax是0,bx是原来ax中的数字
mov cx,10d
mul cx
xchg ax,bx
;把ax中的数字加到bx中
add bx,ax
jmp input
exit:
ret
DecToBinary endp
;_______________________________________________________________
BinaryToHex proc near
mov ch,4;cx高位设置为4
rotate:
mov cl,4 ;cx低位设置为4
rol bx,cl ;bx中的数左移4位
mov al,bl ;移到al
and al,0fh
add al,30h ;把十六进制转换成ASCII
cmp al,3ah ;判断是否大于9
jl print ;如果小于9直接输出
add al,7h ;A-F
print:
mov dl,al ;把要打印的ASCII放到dl中
mov ah,2
int 21h ;调用dos
dec ch
jnz rotate
ret
BinaryToHex endp
code ends
end main
十六进制转十进制:
code segment
main proc far
assume cs:code
star:
push ds
sub ax,ax
push ax
call hToB
call bTOD
jmp main
ret
main endp
;____________________________________________
hToB proc near
newchar:
mov bx,0
mov,ah,1
int 21h
sub al,30h;ascii码转成二进制
jl exit
cmp al,10d ;是否大于9
jl add_to
sub al,27h ;ascii码转成二进制
cmp al,0ah
jl exit ;小于a则没有字母,直接跳出
cmp al,10h
jge exit
add_to:
mov cl,4
shl bx,cl
mov ah,0
add bx,ax
jmp newchar
exit:
ret
hToB endp
;____________________________________________
bTOD proc near
mov cx,10000d
call dec_div
mov cx,1000d
call dec_div
mov cx,100d
call dec_div
mov cx,10d
call dec_div
mov cx,1d
call dec_div
ret
;____________________________________________
dec_div proc near
mov ax,bx ;低位
mov dx,0 ;高位置0
div cx
mov bx,dx
mov dl,al;要输出的放入dl中
add dl,30h ;转换成ascii
mov ah,2
int 21h
ret
dec_div endp
;____________________________________________
bTOD endp
code ends
end start
第七章
宏定义
宏定义、宏调用、宏展开
- 定义:
macro_name macro [dummy parameter list] 宏定义名 macro 哑元表(形参) · · · endm - 调用
macro_name [actual parameter list]
宏定义体=>复制到宏定义位置
&操作符
展开时可以把&前后两个符号合并形成一个符号,这个符号可以是操作码、操作数或者一个字符串
%expresion
把跟在%之后的表达式的值转换成当前基数下的数,在展开期间用这个数取代哑元
宏库的调用
扩展名为.MAC或者.INC 引用格式:
include c:\macro.mac
子程序与宏定义的区别:
使用子程序,需要为转子和返回、保存和恢复寄存器以及参数的传递等增加程序的额外开销,子程序是在程序运行期间由主程序调用的,他只占有自身大小的一个空间;而宏调用是在汇编期间展开的,每调用一次都把宏展开一次因而占用空间与调用次数有关,次数越多占用空间越大。
第八章
中断
软件中断:
- 由中断指令引起
- 由于cpu某些错误引起
- 为调试程序debug设置的中断
硬件中断:
- 非屏蔽中断
- 来自外部设备的中断(可屏蔽中断)
FLAGS中:IF=1 允许中断,IF=0 不允许中断
STI:IF置1
CLI:IF置0
中断号*4 -> 偏移地址 -> 下一个字 段地址
中断过程:
- 取中断号N
- 标志寄存器flags入栈
- 代码段寄存器cs入栈
- 指令计数器ip入栈
- IF=0,TF=0
- 从中断向量表取4 * N的字内容送ip,取4 * N + 2中的字送cs
- 转中断处理程序
第九章
1号功能
从键盘输入一个字符并回显在屏幕上 al=字符
2号功能
显示器输出,要输出的字符放在dl中
9号功能
显示字符串,DS:DX=串地址,必须要$结尾
A号功能
键盘输入到缓冲区,DS:DX缓冲区首地址,DS:DX+1=实际输入的字符