ASM16 21 函数补充和中断指令
函数补充123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103MyStack segment stack db 256 dup(?)MyStack endsMyData segmentMY_MSG1 db "Hello World1!",0dh,0ah,'$'MY_MSG2 db "Hello World2!",0dh,0ah,'$'MyData endsMyCode2 segment call far ptr MY_SUBMY_SUB: push bp mov bp,sp ;保存栈底 mov ax,[bp+6] su ...
ASM16 20 花指令和函数调用
花指令1234567891011121314151617181920212223242526MyStack segment stack db 256 dup(?)MyStack endsMyData segmentMY_MSG db "Hello World!",0dh,0ah,'$'MyData endsMyCode segmentMAIN: mov ax,MyData mov ds,ax mov es,ax jmp LABEL1 db 0b8h ;花指令LABEL1: mov dx,offset MY_MSG mov ah,09h int 21h mov ax,4c00h int 21hMyCode endsend MAIN
这种程序可以正常运行,但是反汇编代码时会分析错误,因为有数据的干扰
正常运行
编译器会把b8当成代码进行分析,从而导致后面分析处于出来的代码都是错的
但是如果找到花指令并从正确的地方开始分析,则分析出来的代码是正确的
解决方法是找到花指令并nop
...
ASM16 19 通讯录
通讯录123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177MyStack segment stack db 256 dup(?)MyStack endsMyData segmentMENU1 db & ...
ASM16 18 循环语句
简单的do-while,先循环再判断
123456789101112131415161718192021222324252627MyStack segment stack db 256 dup(?)MyStack endsMyData segment MSG1 db "Hello World!",0dh,0ah,'$'MyData endsMyCode segment MAIN: mov ax,MyData mov ds,ax mov es,ax ;循环 do-while mov cx,3LOOP1: inc ax dec cx jnz LOOP1 mov ax,4c00h int 21hMyCode endsend MAIN
常规的while写法,先判断再循环
12345678910111213141516171819202122232 ...
ASM16 17 判断语句
CPU采用流水线设计,跳转时的运行周期更长,则写代码时要尽量减少跳转(跳转断流水线)
流水线设计思想设计的处理器是五级流水处理器,取指,译码,执行,访存,回写。(1)取指: 取出指令存储器中的指令,PC值递增,准备取下一条指令。(2)译码:对指令进行译码,依据译码结果,从32个通用寄存器中取出源操作数,有的 指令要求两个源操作数都是寄存器的值,比如or指令,有的指令要求其中一 个源操作数是指令中立即数的扩展,比如ori指令,所以这里有两个复用器, 用于依据指令要求,确定参与运算的操作数,最终确定的两个操作数会送到执 行阶段。(3)执行:依据译码阶段送入的源操作数、操作码,进行运算,对于ori指令而言, 就是进行逻辑“或”运算,运算结果传递到访存阶段。(4)访存:对于ori指令,在访存阶段没有任何操作,直接将运算结果向下传递到回写阶 段。(5)回写:将运算结果保存到目的寄存器。
在程序指令依次执行的情况下,CPU流水线条数和CPU性能成正比。但当程序指令出现跳转或分支结构时就要另当别论了。比如当指令是jmp (无条件的转移到指令指定的地址去执行从该地址开始的命令)指令时,jmp指令会直接 ...
ASM16 16 BCD码和控制转移类指令
BCD码
二进制编码的十进制数:一位十进制数用4位二进制编码来表示
8086支持压缩BCD码和非压缩BCD码的调整运算
真值
8
64
二进制编码
08H
40H
压缩BCD码
08H
64H
非压缩BCD码
08H
0604H
压缩BCD码加、减调整指令
使用DAA或DAS指令前,应先执行以AL为目的操作数的加法或减法指令
非压缩BCD码加、减调整指令
使用AAA或AAS指令前应先执行以AL为目的操作数的加法或减法指令
AAA和AAS指令在调整中产生了进位或借位,则AH要加上进位或减去借位,同时CF=AF=1,否则CF=AF=0;它们对其他标志无定义
非压缩BCD码乘、除调整指令
AAM指令跟在字节乘MUL之后,将乘积调整位非压缩BCD码
AAD指令跟在字节除DIV之前,先将非压缩BCD码的被除数调整为二进制数
AAM和AAD指令根据结果设置SF、ZF和PF,但对OF、CF和AF无定义
123456789mov al,19h ;bcd压缩码 19+1==>20 inc al ;16运算结果调整 ...
ASM16 14-15 算术运算类指令
算术运算类指令
四则运算是计算机经常进行的一种操作。算术运算指令实现二进制(和十进制)数据的四则运算
请注意算术运算类指令对标志的影响
掌握:ADD/ADC/INC、SUB/SBB/DEC/NEG/CMP
熟悉:MUL/IMUL、DIV/IDIV
理解:CBW/CWD、DAA/DAS、AAA/AAS/AAM/AAD
加法指令ADD
ADD指令将源与目的操作数相加,结果送到目的操作数
ADD指令按状态标志的定义相应设置
带进位加法指令ADC
ADC指令将源与目的操作数相加,再加上进位CF标志,结果送到目的操作数
ADC指令按状态标志的定义相应设置
ADC指令主要与ADD配合,实现多精度加法运算
减法指令SUB(subtract)
SUB指令将目的操作数减去源操作数,结果送到目的操作数
SUB指令按照定义相应设置状态标志
带借位减法指令SBB
SBB指令将目的操作数减去源操作数,再减去借位CF(进位),结果送到目的操作数
SBB ...
ASM16 13 数据传送类指令
数据传送类指令
数据传送是计算机中最基本、最重要的一种操作
传送指令也是最常使用的一类指令
传送指令把数据从一个位置传送到另一个位置
除标志寄存器传送指令外,均不影响标志位
重点掌握 MOV XCHG XLAT PUSH POP LEA
通用数据传送指令
提供方便灵活的通用传送操作
有3条指令 MOV XCHG XLAT
传送指令MOV(move)
把一个字节或字的操作数从源地址传送至目的地址
1234MOV reg/mem,imm ;立即数送寄存器或主存MOV reg/mem/seg,reg ;寄存器送(段)寄存器或主存MOV reg/seg,mem ;主存送(段)寄存器MOV reg/mem,seg ;段寄存器送寄存器或主存
非法传送
两个操作数的类型不一致
例如源操作数是字节,而目的操作数是字;或相反
两个操作数不能都是存储器
传送指令很灵活,但主存之间的直接传送却不允许
段寄存器的操作有一些限制
段寄存器属专用寄存器,对他们的操作能力有限
两个操作数的类型要一致
绝大多数双操作数指令,除非特别说明,目的操作数与源操作数必须一致,否则为非法指令
1MOV ...
ASM16 12 键盘输入并回显、操作文件
键盘输入并回显把01传给AH,则可以实现键盘输入并回显,如果输入成功则AL为输入的字符
12345678910111213141516171819202122232425262728MyStack segment stack ;stack表明是堆栈段,则之后系统给地址会从大到小,而且系统会自动把该段的基址送入ss寄存器 db 256 dup(?)MyStack endsMyData segment ;数据段 db 03,04,05,06 string db "Hello World$"MyData endsMyCode segment ;代码段start: ;告诉编译器代码从此处开始 mov ax,MyData ;获取段基址 mov ds,ax ;将段基址送入寄存器 mov es,ax ;键盘输入并回显 mov ah,01 int 21h mov dx,offset ...
ASM16 11 hello world
写一个简单的hello world程序
123456789101112131415161718192021222324MyStack segment stack ;stack表明是堆栈段,则之后系统给地址会从大到小,而且系统会自动把该段的基址送入ss寄存器 db 256 dup(?)MyStack endsMyData segment ;数据段 db 03,04,05,06 string db "Hello World$"MyData endsMyCode segment ;代码段start: ;告诉编译器代码从此处开始 mov ax,MyData ;获取段基址 mov ds,ax ;将段基址送入寄存器 mov es,ax mov dx,offset string ;==>mov dx,word ptr[0]==>mov dx,0 ;获取hello world在代码段的 ...