汇编基础

打印 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所能存储的范围? 1 答: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 1 2 3 2. XOR XX,XX ; 清零 XX ,CF标志位也会清零 3. 显示一个字符( 显示的一定是 DL中的内容 ) mov AH,02H int 21H 1 2 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 , 定义字节型数据 1 2 2. DS,CS,SS,ES 不能直接给数据,必须通过通用寄存器(ax,bx,cx,dx )给他们赋值 比如: MOV DS,DATA 会出错 1 3. sp 一次移动两个单元(即一个字) 4. push指令 –> ①SP-2 –> ②将**字型数据**存放到SS:SP地址中 pop指令 –> ①将SS:SP地址的**字型**数据取出来 –> ②SP+2 1 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 1 2 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 打印 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所能存储的范围? 1 答: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 1 2 3 2. XOR XX,XX ; 清零 XX ,CF标志位也会清零 3. 显示一个字符( 显示的一定是 DL中的内容 ) mov AH,02H int 21H 1 2 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 , 定义字节型数据 1 2 2. DS,CS,SS,ES 不能直接给数据,必须通过通用寄存器(ax,bx,cx,dx )给他们赋值 比如: MOV DS,DATA 会出错 1 3. sp 一次移动两个单元(即一个字) 4. push指令 –> ①SP-2 –> ②将**字型数据**存放到SS:SP地址中 pop指令 –> ①将SS:SP地址的**字型**数据取出来 –> ②SP+2 1 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 1 2 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线上直播课程封面1.png

打赏 支付宝打赏 微信打赏