今天汇编终于到了,马买皮,早知道这么慢就去京东上买了。
我为什么要学汇编
关于汇编,以前看《深入理解计算机系统》的时候就大致看了一蛤,当然是远远不够的,而且这本书我从大二看到现在也还没看完……
而我稍微浏览了一下我们这学期的教科书,跟那个煞笔老师一样让我感到很遗憾的是,书上也完全没有汇编。
要是真的学得这么浅的话,就不止是让人遗憾,更是让人觉得失望了。
是的,我已经很自然的认为学习操作系统就需要学并用到汇编,比如MBR还想用什么写,那是直接接触硬件的部分,除了汇编没有其他选择。emmmmm,据说汇编还有其他在debug等追根溯源上作为终极武器有很强的功能,据说啦,据说。不过看了一点之后发现汇编和操作系统在一些部分是很通用的。
另外,在《操作系统真象还原》其实最基础的假设就是读者都已经学了汇编。
顺便吐槽一句,王爽的《汇编语言》居然平台居然是Windows的,醉了。
正文
顺便附上我写的第一个汇编程序
<code class="language-assembly">assume cs:codesg
codesg segment
mv ax,2
add ax,ax
add ax,ax
mov ax,4c00h
int 21h
codesg ends
end
虽然连结果都打印不出来,但还是挺兴奋的。
至此,全书已看完一半了……
第八章 数据处理的两个基本问题
- 8086 CPU中,只有bx,si,di,dp四个寄存器才能用于内存寻址。并且,对于两个两个寄存器两两组合的情况,只有bx,bp 与 si,di 分别两两组合形成的4种组合方案。
- 内存寻址方式在 本书 P164 中有很好的总结,这里不再赘述。
- 指定处理的数据长度的方法有二: 1. 通过寄存器名指明数据的尺寸。 因为位数不同的寄存器无法相互操作。
- 通过
操作符 X ptr
的方式指定。其中byte ptr
指的是一个字节单位;word ptr
指的是一个字单位;dword ptr
指的是一个双字单位。 - 在C语言中,我们经常可以看到,如:
dec.cp[i]
代表的是名为dec
的结构体中首地址为cp
的变量中的第i
个单元。而我们在汇编中做法存在bx.10h[si]
。仔细一想的话,C语言中包含了很多与汇编相通的语法。只不过包了一层外衣。 - div指令。语法是
div 除数(reg/内存单元)
,而我们的被除数一般优先放在 ax 中,其次放在 dx中。其商也是优先放在 ax 中,其次放在 dx 中。 - 伪指令 db,dw,dd。以下是三个伪指令的缩写,看了英文就会明白它的意思。 - db: define byte
- dw: define word
- dd: define dword
- 指令操作符 dup。表示重复定义元素。语法为
db/dw/dd n dup (元素)
其中n
为重复次数。在()
为初值。比如db 4 dup (0)
等同于db 0,0,0,0
第九章 指令转移的原理
- 指令操作符 offset 。 offset 是偏移的意思。它的指令含义是获得标号的偏移地址。语法:
offset 标号
- 指令操作符 nop 。 申请一个什么都没有的字节单位的机器码。
- cpu在执行jmp指令的时候无须知道目标地址。jmp指令只考虑与当前指令地址的偏移量。、
- jmp 语法小节: -
jmp short 标号
,偏移量在有符号字节单元内的段内转移。范围即[-128,127]
jmp near ptr 标号
,偏移量在有符号字单元内的段内转移。范围即[-32768,32767]jmp far ptr 标号
,段间转移。用标号处的SA,EA来修改CS,IP。jmp 16位 reg
,用reg中的值来改变 ip 。jmp word ptr 内存单元
,段内转移。内存单元中存的是EA。jmp dword ptr 内存单元
,段间转移。内存单元中高位字存SA,低位字存EA。
- jcxz 标号。含义为 “jmp if cx equal to zero”。等同于C语句
if((cx)==0) jmp short 标号;
- 补充,loop本质上也是有jmp指令而来,loop指令跳转的也是短转移。即其jmp范围为[-128,127]
第十章 call与ret指令
- ret 指令: 等同于
pop ip
。 - retf 指令: 等同于
pop ip pop cs
指令。 - call 指令: 指令将进行两步操作,先将当前 ip 或者是 cs和ip 压入栈中,再是转移。其语法有 1.
call 标号
:段内转移,等同于 1.push ip
jmp near ptr 标号
call far ptr 标号
:段间转移,等同于 1.push cs
push ip
jmp far ptr 标号
call 16位reg
:段内转移,用寄存器中的数据进行转移,等同于 1.push ip
jmp 16位寄存器
call word ptr 内存单元
:段内转移,用内存数据进行转移,等同于 1.push ip
jmp word ptr 内存单元地址
call dword ptr 内存单元
:段间转移,用内存数据进行转移,等同于 1.push cs
push ip
jmp dword ptr 内存单元
- 仔细观察一下,将call与ret结合起来使用就是一个函数的功能。
- 批量参数数据的传递可以通过申请内存并保存首地址的方式来实现。
- 指令操作符 mul:两个相乘的数,要么是8位,要么是16位,默认都放在ax寄存器中。另一个数字放在其他16位寄存器或者内存单元中。而其结果优先放在 ax 中,其次放在 dx 中。
- 寄存器是有限的,在使用call之后应首先把当前使用的寄存器的值预先放在栈中,在ret之前把栈的数据还原。
第十一章 标志寄存器
标志寄存器是8086的最后一个寄存器。也称为flag寄存器。flag寄存器是按位起作用的。其有效位如下
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
OF | DF | IF | TF | SF | ZF | AF | PF | CF |
- CF: Carry Flag 。进位标志。在无符号计算时如果存在进位则为 1 。否则为 0 。
- PF: Parity Flag 。奇偶标志。指令计算结果为偶数时为 1, 否则为 0 。
- AF: Auxiliar Carry Flag。辅助进位标志。 意义不明。
- ZF: Zero Flag。零标志。 指令结果为 0 则为 1。否则为 0。
- SF: Sigh Flag。符号标志。 指令结果为 负数 则为 1。否则为 0 。
- TF: Trace Flag。轨迹标志。 当TF为 1 时,执行完当前指令后将引起单步中断。
- IF: Interrupt Flag。中断标志。 功能与 TF 一致。
- DF: Direction Flag。方向标志。 DF为0时,每次指令操作后si,di递增,否则递减。
- OF: Overflow Flag。溢出标志。在有符号计算时如果发生溢出,则为 1 ,否则为 0。
其他:
- adc 指令。带进位加法指令。
adc ax,bx
等同于(ax)=(ax)+(bx)+CF
,一般用于大数操作。 - sbb 指令。带借位减法指令。与adc指令类似。
- cmp 指令。cmp指令的功能类似于 减法指令。cmp指令虽然不会保存结果,但是会影响flag寄存器。通过flag寄存器的值,来判断两个数之间的大小关系。
- 以ax,bx为例,以下为无符号数大小比较之法: - $ ZF = 1 \rightarrow (ax) = (bx) $
- $ ZF = 0 \rightarrow (ax) \neq (bx) $
- $ CF = 1 \rightarrow (ax) < (bx) $
- $ CF = 0 \rightarrow (ax) \geq (bx) $
- $ CF = 0 && ZF = 0 \rightarrow (ax) > (bx) $
- $ CF = 1 && ZF = 1 \rightarrow (ax) \leq (bx) $
- 以ax,bx为例,以下为有符号数大小比较之法: - $ ZF = 1 \rightarrow (ax) = (bx) $
- $ ZF = 0 \rightarrow (ax) \neq (bx) $
- $ SF ^ OF = 1 \rightarrow (ax) < (bx) $
- $ SF = 0 && OF = 0 \rightarrow (ax) \geq (bx) $
- $ SF = 1 && OF = 1 \rightarrow (ax) > (bx) $
- pushf和popf。将flag寄存器压入栈中或者从栈中弹出数据存到flag寄存器中。
- movsb / movsw 指令。将 ds:si 指向的内存单元的数据(字节/字)送入 es :di中,然后根据flag寄存器中的df位的值,将si,di递增或递减(1位/2位)。
- cld 指令将flag寄存器中的df位置变为 0,std指令则为置1 。
- 基于flag寄存器的条件转移,见表1。
- dos的debug中对于flag寄存器的表示,见表2。
指令 | 含义 | 检测的相关标志位 |
---|---|---|
je | 等于则转移 | $ ZF = 1 $ |
jne | 不等于则转移 | $ ZF = 0 $ |
jb | 低于则转移 | $CF =1 $ |
jnb | 不低于则转移 | $ CF = 0 $ |
ja | 高于则转移 | $ CF = 0 \&\& ZF = 0 $ |
jna | 不高于则转移 | $ CF = 1 || ZF = 1 $ |
标志 | 值为 1 的标记 | 值为 0 的标志 |
---|---|---|
OF | OV | NV |
SF | NG | PL |
ZF | ZR | NZ |
PF | PE | PO |
CF | CY | NC |
DF | DN | UP |
- 内存段有4种产生方式 - 除法错误。中断类型码: 0
- 单步执行。中断类型码: 1
- 执行 into 指令。中断类型码: 4
- 执行 int 指令。中断类型码: 其他