写这个系列文章的次要目标是记录书中重要的知识点,并和大家分享一些集体了解与实际。因为笔记中的知识点比拟零散,而书中零碎的介绍了一个 x86-16 处理器在实模式下的工作原理以及如何应用汇编语言与其进行“沟通”,所以举荐想要零碎学习的敌人们去学习这本书。当咱们把握了实模式的工作原理之后,就能够进一步钻研起初呈现的其余运行模式(如保护模式)。除此之外,相熟汇编语言有助于咱们把握下层语言(如 C)的执行原理,因为它们都要对汇编(机器码)进行形象,而汇编程序就是基于 CPU 的执行机理写进去的。
第九章
转移 行为 分类
- 段内转移 (只批改
IP
, 依据转移的范畴不同又分为: 短转移 和 近转移) - 段间转移(同时批改
CS
和IP
)
jmp
指令的两种实现差别
在个别的汇编指令中,立刻数不管示意一个数据还是内存单元的偏移地址,都会在对应的机器指令中呈现。
-
基于 转移的间隔 ——指令中不蕴含目标地址,而蕴含的是 位移量(向前或向后挪动的间隔)
- 长处,可 浮动拆卸,即位移量不变的状况下,这段程序可在任何中央执行
- 基于要转移的目标地址
以上两个维度的汇总
基于转移的间隔(间接转移) | 基于要转移的目标地址(间接转移) | |
---|---|---|
段内转移 | jmp short Label jmp Label 、jmp near ptr Label |
jmp 某一非法 16 位寄存器 ——将寄存器中的内容写入 IP jmp word ptr 地址 ——转移到目标偏移地址 |
段间转移 | jmp far ptr Label (注:它也可能实现段内转移的成果)jmp dword ptr 地址 (h_word= 段地址,l_word= 目标偏移地址) |
-
jmp short Label
: 翻译成的机器码为EB??H
, ?? 代表 8 位的位移量(这种形式是 短转移)实质为:IP = IP + 8 位的位移量【重点(容易被疏忽):CPU 在执行该指令时,是应用这个位移量来计算 IP 的】- short 指明此处的位移为 8 位位移,范畴是 -128~127, 用【补码】示意 - 8 位的位移量 = 标号处的地址 - jmp 指令后的第一个字节的地址,编译器在【编译时】算出
-
为什么是
jmp
指令后的第一个字节的地址aj
?为什么这么设计呢?因为取址之后(执行之前)IP
寄存器中的地址会被设置为该地址aj
,这样在执行转移指令时,能够直接参与目标偏移地址的计算!- 编译时:
disp=as-aj
, 执行指令时:IP(as) = IP(aj) + disp(位移量)
即间接实现该指令的性能
- 编译时:
-
jmp near ptr Label
(近转移,实质与短转移雷同,区别仅仅是它反对16 位的位移量)-
jmp far ptr Label
(远转移)CS 设置为 标号所在段的【段地址】IP 设置为 标号在该段中的【偏移地址】
masm 对 jmp 外部转移的编译实现
【条件转移】和【循环指令】是对【短转移】的性能扩大
-
jcxz
指令的伪代码:...... if ((cx) == 0) {jmp short s} s: ......
-
loop
指令的伪代码s: ...... (cx)--; if ((cx) != 0) {jmp short s} ......
试验八:剖析一个奇怪的程序
留神:是将 jmp short s1
的机器码 EBF6
拷贝至 076C:0008~076C:0009
两个存储单元中,F6
是 -10
的补码,示意位移量
其实 补码 F6
示意什么有符号数,能够不必图片中的办法计算,而应用以下办法计算更为简略:
-
因为补码
1111 1111
示意十进制有符号数-1
, 这个-1
的计算形式是:$$
-1 = -1*2^7 + 1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
$$$$
= -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1
$$ -
那么补码
1111 0110(0xF6)
就等于:$$
-1*2^7 + 1*2^6 + 1*2^5 + 1*2^4 + 0*2^3 + 1*2^2 + 1*2^1 + 0*2^0
$$$$
(-1*2^7+1*2^6+1*2^5+1*2^4+1*2^3+1*2^2+1*2^1+1*2^0) – 1*2^3 – 1*2^0 = -1 – 8 – 1 = -10
$$
试验九:80x25
黑白字符模式缓冲区输入程序
- 显示缓冲区:
B8000H~BFFFFH(共 32KB, 8 页,每页 4KB)
80x25
——每页由 25 行组成,每行由 80 个字符(160byte)组成- 注:dosbox 中执行完可执行文件,输入后果会被向上顶一行(弹出输出提示符导致),所以以下程序的输入就显示在 11,12,13 行了
; 在屏幕两头别离显示黑底绿色、绿底红色、白底蓝色的字符串 'welcome to masm!'
; 题目要求屏幕两头显示?那就 12,13,14 行显示
assume cs:codesg, ds:datasg, ss:stacksg
datasg segment
db 'welcome to masm!'
db 02H, 24H, 71H ; 三种属性:黑底绿色、绿底红色、白底蓝色
datasg ends
stacksg segment
dd 0,0,0,0
stacksg ends
codesg segment
start: mov ax, datasg
mov ds, ax
mov ax, stacksg
mov ss, ax
mov sp, 10H
mov ax, 0B800H ; masm 汇编器要求立刻数不能以字母结尾
mov es, ax
mov bx, 0
mov bp, 16
mov cx, 3 ; 共写入 3 行
s0: mov si, 0
mov di, 1824 ; di=1760+64, 1760 是 12 行第一字节的 offset, 每行两头地位的 offset=64
add di, bx ; 计算每一行开始写入的偏移地址
mov ah, ds:[bp] ; 该行要显示的属性值
push cx ; 保留
mov cx, 16
s: mov al, [si]
mov es:[di], al ; 显存区域:字符低字节示意 ASCII
inc di
mov es:[di], ah ; 字符高字节对应色彩属性
inc si
inc di
loop s
add bx, 160 ; 0-160-320 (管制写入下一行)
inc bp ; 16-17-18(管制获取下一行的属性值)
pop cx ; 复原
loop s0
mov ax, 4c00H
int 21H
codesg ends
end start
第十章
模块化程序设计
-
call
和ret
指令配合应用(近转移)call
等价于:push IP + jmp ...
- ret 等价于:
pop IP
-
call 和 retf 指令配合应用(远转移)
- call 等价于:
push CS + push IP + jmp ...
- retf 等价于:
pop IP + pop CS
(留神这个程序)
- call 等价于:
call 指令
相当于 将 call 指令之后的那一个指令 的IP
或 CS+IP
压栈之后,进行 jmp
转移。
反对 近转移 或远转移 ,不反对 短转移。
-
call Label
push IP
jmp near ptr Label
-
call far ptr Label
push CS
push IP
jmp far ptr Label
-
call 16 位寄存器
push IP
jmp 16 位寄存器
-
call word ptr 内存地址
push IP
jmp word ptr 内存地址
-
call dword ptr 内存地址
push CS
push IP
jmp dword ptr 内存地址
总结——【目前曾经介绍的】转移指令对应的机器码
call 转移指令 | 机器码 | jmp 转移指令 | 机器码 |
---|---|---|---|
call L |
E8 ????(16 位位移量) | jmp near ptr L |
E9 ???? |
call far ptr L |
9A ???? ????<br/> 标号在段中的偏移地址 标号所在段地址 | jmp far ptr L |
EA ???? ???? |
call ax、call bx |
FFD0、FFD3 | jmp ax、jmp bx |
FFE0、FFE3 |
call word ptr addr |
FF160000 (todo) | jmp word ptr addr |
FF260000 (todo) |
call dword ptr addr |
FF1E0000 (todo) | jmp dword ptr addr |
FF2E0000 (todo) |
8086 中乘法的计算规定
汇编指令:mul 乘数(在内存或某个寄存器中)
,【被乘数和乘数】要么都是 8 位,要么都是 16 位
8 位乘数 | 16 位乘数 | |
---|---|---|
被乘数 | 8 位——在 al 中 |
16 位——在 ax 中 |
后果 | ax 中 |
dx 存高 16 位、ax 存低 16 位 |
试验十:编写子程序
(1)指定地位打印字符串
exp10_1.asm
(2)解决除法溢出的问题
exp10_2.asm
(3)二进制转十进制,打印
exp10_3.asm