第一节 显示字符串
jmp near start
message db '1+2+3+···+100='
;字符串
;==db '1','+','2','+','3','+','·','+','·','+','·','+','100','='
start:
mov ax, 0x7c0
mov ds, ax
;访问内存单元,7c0为访问内存开始的位置
mov ax, 0xb800
;访问显存,b800为访问显存开始的位置
mov es, ax
mov si,message
mov di,0
mov cx, start-message
@g:
mov al, [si]
;[si](ds:si)指向db指令所声明的第一个存储单元
;将字符1的ACSII码存入al寄存器中
mov [es:di], al
;[es:di]指向显存的第一个存储单元
;将字符1的ASCII码存入显存的第一个存储单元
inc di
;为下一行代码存入字符属性提前做好准备
mov byte [es:di], 0x07
inc di
inc si
;为下一次循环提前做好准备
loop @g
第二节 1到100的累加
xor ax, ax
mov cx, 1
@f:
add ax, cx;0+1+2+3+···+100
inc cx ;2->3->4->···->100->101
cmp cx, 100
jle @f
;小于等于则跳转
第三节 JLE
和CMP
-
以下条件转移用于无符号数据:
-
符号 说明 测试的标志 JE/JZ 相等则转移或为零则转移 ZF JNE/JNZ 不相等则转移或不为零则转移 ZF JA/JNBE 高于则转移或不低于等于则转移 CF,ZF JAE/JNB 高于等于则转移或不低于则转移 CF JB/JNAE 低于则转移或不高于等于则转移 CF JBE/JNA 低于等于则转移或不高于则转移 AF,CF
-
-
以下条件转移用于有符号数
-
符号 说明 测试的标志 JE/JZ 相等则转移或为零则转移 ZF JNE/JNZ 不相等则转移或不为零则转移 ZF JG/JNLE 大于则转移或不小于等于则转移 OF,SF,ZF JGE/JNL 大于等于则转移或不小于则转移 OF,SF JL/JNGE 小于则转移或不大于等于则转移 OF,SF JLE/JNG 小于等于则转移或不大于则转移 OF,SF,ZF
-
-
以下条件转移指令含有专门用途
-
符号 说明 测试的标志 JCXZ 若CX为零则转移 无 JC 进位为1则转移(和JB相同) CF JNC 进位为0则转移 CF JO 溢出则转移 OF JNO 不溢出则转移 OF JP/JPE 奇偶位为1则转移或奇偶性为偶则转移 PF JNP/JPO 奇偶位为0则转移或奇偶性为奇则转移 PF JS 符号位为1(负)则转移 SF JNS 符号位为0(正)则转移 SF
-
-
cmp cx, 100 ;比较指令,执行减法操作,目的操作数-源操作数(2-100) jle @f
-
(-128~127)
有符号数(0~255)
无符号数2 0000 0010 2 2 100 - 0110 0100 100 100 1001 1110 -98(-98) 158(-98) OF = 0 CF = 1 -
SF:
- 被减数 < 减数 SF = 1 ----> CX = 0 ~ 99
- 被减数-减数,结果为负,故为1
- 被减数 ≥ 减数 SF = 0 ----> CX = 100
- 被减数-减数,结果为正,故为0
- 被减数 < 减数 SF = 1 ----> CX = 0 ~ 99
-
OF:
- CX = 0~100 ----> OF = 0
-
ZF:
- CX = 100 ----> ZF = 1
-
JLE的跳转条件:只有在被减数小于等于100时才会进行跳转
- SF ≠ OF CX = 0 ~99 被减数 < 减数
- ZF = 1 CX = 100 被减数 = 减数
第四节 数据结构–栈
-
栈段寄存器
SS
- 偏移地址被指定为栈指针寄存器
SP
- 偏移地址被指定为栈指针寄存器
-
通过数据段寄存器DS和附加段寄存器ES访问内存单元的方式:
-
手动为其配备偏移地址
-
mov al, [si] mov [es: di], al
-
-
通过代码段寄存器CS访问内存单元的方式:
-
偏移地址被指定为指令指针寄存器IP
-
处理器会自动的根据CS和IP的值去访问它们所指向的内存单元,所以不存在一个显示的访问方式
-
mov [cs: di], al ;此行代码的作用和使用DS、ES寄存器相同 ;既可以用于处理器自动访问内存单元,也可以用于操作者访问内存单元
-
-
通过SS寄存器,访问内存单元的方式
- 偏移地址被指定为堆栈寄存器SP
- push指令,用于写入数据(压栈)
- pop指令,用于读取数据(出栈)
-
PUSH AX (写入数据)
-
push指令先减2再存入数据
-
- SP - 操作数的数据宽度
PUSH指令最低可以接收的数据宽度是16位(2个字节)
8086处理器 —> push指令的操作数必须是16位(2个字节)的
PUSH AL —> 错误
8086处理器 —> SP -2
-
- 将操作数存入
SS:SP
所指向的内存单元中
- 将操作数存入
-
push指令
存入的数据所占用的内存称为栈段
- 栈的推进方向为向下推进,与程序的执行方向相反
- 后进先出(抽象为倒放的容器进行理解,先存入的数据会被放在倒放的容器的最顶端,故最后被取出)
-
-
POP DX (读取数据)
-
pop指令是push指令的逆运算,先取出数据再加2
-
- 从
SS:SP
所指向的内存单元开始,取出2个字节(16位)的数据到DX寄存器中 - 8086处理器 —> SP + 2
- 从
-
第五节 分解各个数位并压栈
xor cx, cx
mov ss, cx
mov sp, cx
;将栈段寄存器、栈指针寄存器初始化为0
mov bx, 10
@d:
inc cx
;记录压栈的次数
xor dx, dx
div bx
add dx, 0x30
;余数+0x30,得到个位数值的ASCII码
push dx
;将各位数值的ASCII码进行压栈,存入栈段中
cmp ax, 0
;将ax寄存器中的进行判断,若AX寄存器中的值=0,则跳出循环,向下执行
jne @d
;cmp和jne指令事先不知道循环次数,需对条件进行判断,来决定是否进行循环
;loop指令则是事先明确知道循环次数,根据循环次数决定是否进行循环
第六节 出栈并表示各个数位
@a:
pop dx
;读取最高位数值的ASCII码,进入循环中以此类推
mov [es:di], dl
inc di
mov byte [es:di], 0x07 ;显示字符的颜色属性
inc di
loop @a
;循环次数由CX值(压栈次数)决定,
jmp near $
;无限循环
times 510 - ($ - $$) db 0
;填补字节数
db 0x55, 0xaa
;硬盘第511、512位置处的有效标志