几个汇编入门小例子
一:打印 Hello World
DATA SEGMENT
BUF DB 'HELLO WORLD! THIS IS MY FIRST ASM FILE! $'
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
LEA DX,BUF
MOV AH,09H
INT 21H
MOV AH,4CH
INT 21H
CODE ENDS
END START
小记:
1. 字符串的最后一个字符必须是“$”
2. LEA DX,BUF 等价于 MOV DX,OFFSET BUF
3.通过功能号为 9 的DOS功能调用实现字符串的显示
09H 显示字符串
01H 单个字符的输入
02H 单个字符的输出
二:计算 ffff:0 ~ ffff:b 单元中的数据的和,存储在 dx 中。
分析:
1.运算结果是否会超出dx所能存储的范围?
答:dx ,一个字,有两个字节,16位 ,范围在 0~65535 。ffff:0 ~ ffff:b**内存单元中的数据都是字节型数据**,范围在0~255之间,12个这样的数据相加不会超过65535 ,所以完全可以存放的下!
;实例:计算ffff:0~ffff:b 单元 中的数据的和 ,存储在dx中 。
assume cs:TT
TT segment
start :
mov ax,0ffffh
mov ds,ax
mov dx,0
mov bx,0
mov cx,12
tag:
mov al,[bx]
mov ah,0
add dx,ax
inc bx
loop tag
mov ax,4c00h
int 21h
TT ends
end
小记:
1. cx 用来控制 loop 循环次数
2. 字节对应字节 ,字对应字 。
mov al,[bx]
mov ah,0
add dx,ax
3.汇编中数据必须以0 开头,即 0ffffh ,而不能是 ffffh
三:从键盘输入两个十进制数 ,然后以十进制数的形式输出他们的和 。
分析:
1.键盘输入得到他们的ASCII码值
2.减去30H,得到以非压缩型BCD数形式表示的十进制数字
3.相加并进行调整(AAA )
4.再加上30H ,变为对应的ASCII码值 ,输出即可
DATA SEGMENT
INFOR1 DB "Please input the frist data(<10):$"
INFOR2 DB 0AH,0DH,"Please input the second data(<10):$"
INFOR3 DB 0AH,0DH,"The result is:$ "
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE ,DS:DATA
START :
MOV AX ,DATA
MOV DS,AX
MOV DX ,OFFSET INFOR1 ;显示提示信息
MOV AH,09H
INT 21H
MOV AH,01H ;接受输入
INT 21H ;此时等待用户输入,输入的字符一定存放在AL中
sub AL,30H
MOV BL,AL ;转移到 BL
MOV DX ,OFFSET INFOR2 ;显示提示信息
MOV AH,09H
INT 21H
MOV AH,01H ;另一个数放在 AL 中
INT 21H
sub AL,30H
MOV DX ,OFFSET INFOR3
MOV AH,09H
INT 21H
XOR AH,AH ; 清零 AH ,CF标志位也会清零
add AL,BL
AAA
push AX
MOV DL,AH
add DL,30H
MOV AH,02H
INT 21H
pop AX
MOV DL,AL
add DL,30H
MOV AH,02H
INT 21H
MOV AX,4C00H
INT 21H
CODE ENDS
END START
小记:
1. 从键盘输入一个字符 (输入的字符一定存放在AL中)
mov AH,01H ;接受输入
int 21H ;此时等待用户输入,输入的字符一定存放在AL中
sub AL,30H
2. XOR XX,XX ; 清零 XX ,CF标志位也会清零
3. 显示一个字符( 显示的一定是 DL中的内容 )
mov AH,02H
int 21H
4.因为在途中将有些单词写为小写时出现了错误,所以建议全部写为大些形式 ,保证不会出错 !
5.关于push ax 和 pop ax 。 说实话 ,我还不是很懂,所以不敢乱说 ~_~
6.学习参考链接:(DOS功能调用一览表)https://blog.csdn.net/icurious/article/details/51628343
四:将内存 ffff:0 ~ ffff:b 段元中的数据拷贝到 0:200 ~ 0:20b 单元中 , 0:200 ~ 0:20b 就等价于 0020:0 ~ 0020:b
ASSUME CS:TT
TT SEGMENT
START:
MOV BX,0
MOV CX,12
s: MOV AX,0FFFFH
MOV DS,AX
MOV DL,[BX]
MOV AX,0020H
MOV DS,AX
MOV [BX],DL
INC BX
LOOP s
MOV AX,4C00H
INT 21H
TT ENDS
END
因为每次循环要设置两次ds,效率会比较低下,所以我们来优化一下 :
ASSUME CS:TT
TT SEGMENT
START:
MOV BX,0
MOV AX,0020H
MOV ES,AX
MOV AX,0FFFFH
MOV DS,AX
MOV CX,12
s:
MOV DL,[BX]
MOV ES:[BX],DL
INC BX
LOOP s
MOV AX,4C00H
INT 21H
TT ENDS
END
小记:
1. 因源单元和目标单元相距大于 64KB ,在不同的64KB段里,程序中,每次循环要设置两次ds
2. 使用段前缀 MOV ES:[BX] , DL (其实也很简单了)
3. 0:200h ~ 0:2FFh 共256个字节的空间(几乎不会被使用,什么都不会存放) 可以作为一段安全的空间任意使用
五:将 data 数据段的数据通过栈的性质倒序存入
ASSUME CS:TT,DS:DATA,SS:STACK
DATA SEGMENT
DW 0123H,0456H,0789H,0ABCH,0DEFH,0FEDH,0CBAH,0987H ;数据段原始数据
DATA ENDS
STACK SEGMENT
DW 0,0,0,0,0,0,0,0
STACK ENDS
TT SEGMENT
START: ; CS:IP pointer here
MOV AX,STACK
MOV SS,AX
MOV SP,16 ;栈顶指针指向 16(2*8)
MOV AX,DATA
MOV DS,AX
MOV BX,0
MOV CX,8
tag:PUSH [BX]
ADD BX,2
LOOP tag
MOV BX,0
MOV CX,8
s: POP [BX]
ADD BX,2
LOOP s
MOV AX,4C00H
INT 21H
TT ENDS
END START
小记:
1.
dw 即 define word , 定义字型数据
db 即 define byte , 定义字节型数据
2. DS,CS,SS,ES 不能直接给数据,必须通过通用寄存器(ax,bx,cx,dx )给他们赋值
比如: MOV DS,DATA 会出错
3. sp 一次移动两个单元(即一个字)
4.
push指令 –> ①SP-2 –> ②将**字型数据**存放到SS:SP地址中
pop指令 –> ①将SS:SP地址的**字型**数据取出来 –> ②SP+2
六:输入年龄(如果是三位数就直接输入即可,如果是两位数,第三位数写为0 。比如:032 ),输出其所对应的年龄段名称 。
分析:
1.得到三个数字字符
2.先判断百位是不是 1,如果是1 ,在判断十位大不大于5 ,
大于5,其他物种,小于5,是个老人啊
3.再判断百位是不是0 ,如果不是,其他物种,如果是,判断十位
< 60 child
60~80 middle man
> 80 old man
DATA SEGMENT
INFOR1 DB 0AH,0DH,"Please input your age :$"
INFOR2 DB 0AH,0DH,"Your age is < 60 ,I think you are a child $"
INFOR3 DB 0AH,0DH,"You are a middle man $"
INFOR4 DB 0AH,0DH,"You are a old man $"
INFOR5 DB 0AH,0DH,"You are a other species !$"
AGE DB 0,0,0
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
MOV DX,OFFSET INFOR1
MOV AH,09H
INT 21H
MOV CX,3
MOV BX,OFFSET AGE
tag:
MOV AH,01H ;接受输入
INT 21H ;此时等待用户输入,输入的 one ge 字符一定存放在 AL 中
MOV [BX],AL
INC BX
LOOP tag
MOV BX,OFFSET AGE
CMP [BX],BYTE PTR '1'
JE TEMP ; == 1
CMP BYTE PTR [BX],'0'
JNE OTHER ; != 0
INC BX
CMP [BX],BYTE PTR '6'
JB CHILD
CMP [BX],BYTE PTR'8'
JB MAN
JNB OLD_MAN
JMP PEND
TEMP:
INC BX
CMP [BX],BYTE PTR'5'
JNA OLD_MAN ; <= 5
JA OTHER ; >5
CHILD:
MOV DX,OFFSET INFOR2
MOV AH,09H
INT 21H
JMP PEND ;注意执行完一个分支后应使程序跳出
MAN:
MOV DX,OFFSET INFOR3
MOV AH,09H
INT 21H
JMP PEND
OLD_MAN:
MOV DX,OFFSET INFOR4
MOV AH,09H
INT 21H
JMP PEND
OTHER:
MOV DX,OFFSET INFOR5
MOV AH,09H
INT 21H
JMP PEND
PEND:
MOV AH,4CH
INT 21H
CODE ENDS
END START
小记:
1.字与字节必须对应
CMP [BX],BYTE PTR '1'
JE TEMP ; == 1
2. 检测比较结果的条件转移指令( je 和 jz相同)
je/jz 等于则转移 zf=1
jne/jnz 不等于则转移 zf=0
jb 低于则转移 cf=1
jnb 不低于则转移 cf=0
ja 高于则转移 cf=0且zf=0
jna 不高于则转移 cf=1或zf=1
助记:
e : equal
ne : not equal
b: below ;在下面,到下面,低于;(表示位置)在…下面
nb : not below
a : above ;表示程度)超过;(表示等级)在…之上;(表示位置)在…正上
na : not above