汇编问题列表
(1)8086CPU是多少位的?寄存器有哪些?名称是什么?
8086CPU是16位的
-
寄存器
8个16位通用寄存器:
AX(Accumulator)累加寄存器,可以分为AH(High)和AL(Low)两个8位寄存器。
BX(Base)基地址寄存器,可以分为BH(High)和BL(Low)两个8位寄存器。
CX(Count)计数寄存器,可以分为CH(High)和CL(Low)两个8位寄存器。
DX(Data)数据寄存器,可以分为DH(High)和DL(Low)两个8位寄存器。
SI(Source Index)源变址寄存器
DI(Destination Index)目标变址寄存器
BP(Base Pointer)基地址指针寄存器
SP(Stack Pointer)栈指针寄存器
4个16位段寄存器:
CS(Code Segment)代码段寄存器
DS(Data Segment)数据段寄存器
SS(Stack Segment)栈段寄存器
ES(Extra Segment)附加段寄存器
1个16位指令指针寄存器:
IP(Instruction Pointer)
只能与CS一起使用,只有处理器能改变其内容。
1个标志位寄存器Flags:
按位起作用
详情请见问题(14)
共计14个寄存器
(2)8086CPU的内存分段机制是什么?内存真的分段了吗?
-
内存分段机制
段地址 * 16(或10H) + 偏移地址 = 物理地址
内存只是在逻辑上进行了分段,物理上没有分段。
(3)总线分几种?不同总线的根数代表什么?
总线分为3种:地址总线,数据总线,控制总线。
-
根数意义
总线 意义 地址总线 地址空间(寻址能力) 数据总线 一次传输数据的多少 控制总线 信号的种类
(4)内存地址空间是什么?特点是什么?
-
内存地址空间是什么
计算机对 ROM 和 RAM 等芯片提供的存储空间以线性逻辑整合在一起的连续区域。
-
内存地址空间的特点是:
逻辑上连续,统一编址;
物理上分散,芯片不同;
(5)地址加法器的作用是什么?
地址是20位的,寄存器是16位的,地址加法器将短地址左移4位(乘10H或16D)再加上偏移地址形成20位物理地址。
(6)8086CPU是如何执行指令的?
指令放在内存里,一条接着一条,CPU自己按顺序取出并且执行。
(7)汇编语言是编译性语言还是解释性语言?汇编语言由哪几种部分构成?
- 汇编语言是编译型语言
- 汇编语言分为伪指令和代码指令,每种指令由代码段,数据段,堆栈段和附加段构成。
(8)bochsdbg调试时用到的命令有哪些?都怎么使用?
以下仅整理常用命令,具有强烈主观色彩。
类型 | 命令 | 功能 | 举例 |
---|---|---|---|
中断 | b | 加入断点,后接物理地址 | b 0x7c00 |
blist | 显示现有断点 | ||
d | 删除断点 | ||
执行控制 | c | 继续执行(continue) | |
p或n | 单步执行(遇到 call 和 int 不进入函数、中断内) | ||
s | 单步执行(遇到 call 和 int 进入函数、中断内),后面可以加执行条数 |
s /s 100
|
|
查看寄存器 | r | 显示寄存器状态 | |
sreg | 显示段寄存器状态 | ||
info eflags | 显示标志位寄存器,如果字母为大写表示该位置状态1,否则为0 | ||
查看内存 | xp | 显示内存内容,后接想要显示的多少,单位,以及物理地址。b为字节,h为字,w为双字 | xp /2b 0x7c00 |
print-stack | 查看堆栈 | ||
u | 反汇编,后接行数和物理地址 | u /10 0x7c00 |
|
退出 | q或quit或exit | 停止调试并退出 |
(9)硬盘的CHS、LBA是什么?两者转化的公式是什么?
//TODO
(10)80*25彩色字符模式如何使用?其编程的一般套路是什么?
-
80*25彩色字符模式如何使用?
在80*25彩色字符模式下,显示器可以显示25行,每行80个字符。
一个字符要占两个字节(一个字符的 ACSII 码要占用一个,再加上颜色属性用的一个字节)。
颜色属性的表示方法:
所在位置 7 6 5 4 3 2 1 0 含义 闪烁 背景R 背景G 背景B 高亮 前景R 前景G 前景B -
编程的一般套路
控制要显示的内容所在屏幕上的位置
控制要显示的内容的是否闪烁和高亮,并设置前景和背景颜色。
一般将颜色属性写为16进制或2进制传入显存中想要赋予颜色属性的字符后面的地址中
待续......
(11)内存的串拷贝(rep movsb/movsw)
是如何实现的?
-
movesb
以字节为单位批量传输数据串。
-
movesw
以字为单位批量传输数据串。
-
如何实现的?
执行这条命令时,原始数据串的短地址由 DS 决定,偏移地址由 SI 指定,也就是 DS:SI。传送的字节数或字数由 CS 指定。另外还要指定是正向还是反向传送。
正向传送:由低地址端到高地址端进行传送。
反向传送:由高地址端到低地址端进行传送。
正向传送时,每次传送一个字节,SI 和 DI 自增1。每次传送一个字,SI 和 DI 自增2。
反向传送时,每次传送一个字节,SI 和 DI 自减1。每次传送一个字,SI 和 DI 自减2。
无论正反传送,CX都会自减1。
控制正向还是反向传送的方法是: 控制标志位寄存器中的 DF 标志位。
可通过
cld
指令将 DF 标志位置为0,此时正向传送。可通过
std
指令将 DF 标志位置为1,此时反向传送。rep 表示 repeat,功能:
- rep 后面的指令执行一次
- (cx) = (cx)-1
- 如果(cx)不等于,重复执行后面指令;否则,顺序向下执行,不再重复后面的指令。
传送方式需设置如下(按字节传送):
- cld / std
- 设置源数据段ds,设置目标数据段es
- 设置源偏移si,设置目标偏移di
- 设置传送的次数cx
- rep movsb / movsw
(12)无符号数和有符号数是如何规定的?
无符号数指不区分正负,一律按照自然数处理的数字。
-
有符号数指区分正负,且该数字为整数或者负数要用其最高位进行判断。若最高位是0则该数字为正数,若最高位为1则该数字为负数。
如8位的字节运算环境下,正数的范围是00000000至01111111。负数的范围是10000000至11111111。
Tips: 如果想要判断16进制,需要先将十六进制转换为2进制再进行判断。题目告知为有符号数的前提下,只需判断最高位是0还是1即可。
(13)mul和div的实现过程是什么?(共4种)
- Mul(Multiply)乘法(被乘数*乘数=积)
8位乘法:
- 被乘数放置于 AL 中
- 乘数 SRC 放置于8位通用寄存器或内存。
- 乘积结果为16位,放置于 AX 寄存器中。
mul bl ; mul byte ptr [bx]
16位乘法:
- 被乘数放置于 AX 中
- 乘数 SRC 放置于16位通用寄存器或内存。
- 乘积结果为32位,低16位放置于 AX 寄存器中,高16位放置于 DX 寄存器。
mul bx ; mul word ptr [bx]
- Div(Divide)除法(被除数 / 除数 = 商 。。。余数)
16位除法:
- 被除数放置于 AX 中
- 除数 SRC 放置于8位通用寄存器或内存。
- 商放置于 AL,余数放置于 AH 中。
div bl ; div byte ptr [bx]
32位除法:
- 被除数高16位放置于 DX 寄存器,低16位放置于 AX 中
- 除数 SRC 放置于16位通用寄存器或内存。
- 商放置于 AX,余数放置于 DX 中。
div bx ; div word ptr [bx]
(14)标志位zf、of、cf、pf、sf、df、tf、if、af的作用是什么?是否会判断前5个的值?
标志位 | 0含义 | 1含义 | 备注 |
---|---|---|---|
ZF(Zero flag)零标志位 | 运算结果为1 | 运算结果为0 | |
OF(Overflow flag)溢出标志位 | 计算结果没有溢出 | 符号相同的相加符号变的不一样就溢出 ,符号不同的相减与被减数符号不一样就溢出 | 只对有符号数而言 |
CF(Carry flag)进位借位标志位 | 最高位没有产生进位借位 | 前面的计算中最高位产生进位借位 | 移位操作中保存最高位或最低位溢出的数字 |
PF(Parity flag)奇偶标志位 | 计算结果有奇数个1 | 计算结果有偶数个1 | 结果的低八位 |
SF(Sign flag)符号标志位 | 计算结果为非负 | 计算结果为负 | |
DF(Direction flag)方向标志位 | 正向 | 反向 | 与rep,movesb等配合使用 |
AF(Auxiliary flag)辅助进位借位标志位 | 低四位没有向高四位借位 | 低四位向高四位借位 |
IF, TF 不考,先不写了。
(15)loop循环是如何实现的?
先让 CX 自减1,再判断 CX 是否为0,如果为0则跳转至 loop 后面标明的标号。
(16)jcc语句如何使用?
《x86汇编语言-从实模式到保护模式》第91页表6-1,这玩意儿太多了懒得打。
(17)是否会使用loop或jcc实现一重或二重循环?能否写出程序框架?
会,能。(怠惰中......)
(18)db、dw、dd等作用是什么?times呢?
- db
定义一个以字节为单位的变量。
- dw
定义一个以字为单位的变量。
- dd
定义一个以双字为单位的变量。
- times
重复n次后面的语句。
(19)and、or、xor、not的作用是什么?怎么用?
- and
按位清零。
假如,想要将 000010101B 的位0清零,我们只需要给他 and 上 11111110B 就可以了。
- or
按位置一
假如,想要将 000010101B 的位7清零,我们只需要给他 or 上10000000B 就可以了。
- xor
如果某相同位置上的两个数字同为1或0,则清零,如果不一样则置一。
- not
按位取反,是0变1,是1变0。
(20)栈如何使用?push和pop如何实现?空栈和满栈怎么设置(即sp的值是多少)?
先一顿操作初始化栈段和栈顶。
- 设置栈段寄存器。
mov ax,段地址
mov ss,ax
- 设置栈顶的偏移地址
mov sp,偏移地址
-
push
- (sp) = (sp) – 2
- 放入一个字到SS:SP处
-
pop
- 从SS:SP处取出一个字
- (sp) = (sp) + 2
空栈设置 SP 为0
满栈设置 SP 为1
(21)8086寻址方式有哪些?能否举出一句汇编语句的例子?
- 寄存器寻址
操作的数位于寄存器中,可以直接从寄存器里取得。
mov ax, cx
add bx, 0xf000
inc dx
- 立即寻址
指令的操作数是一个立即数。
add bx, 0xf000
mov dx, label_a
-
内存寻址
- 直接寻址
操作数为一个偏移地址。
mov ax, [0x5c0f] add word [0x0230], 0x5000 xor byte [es:label_b], 0x05
表示内存地址需要用中括号括起来。
- 基址寻址
顺序存放的地址。
buffer dw 0x20, 0x100, 0x0f, 0x300, 0xff00 inc word [buffer] inc word [buffer + 2] inc word [buffer + 4]
mov [bx], dx add byte [bx], 0x55
- 变址寻址
类似于基址寻址,使用变址寄存器。
mov [si], dx add ax, [di] xor word [si], 0x8000
也可以带偏移量。
mov [si + 0x100], al and byte [di + lable_a], 0x80
- 基址变址寻址
允许在机制寄存器和变址寄存器的基础上带一个偏移量。
mov [bx + si + 0x100], al and byte [bx + di + label_a], 0x80
(22)JMP语句分为几种?都是如何实现的?
//TODO
(23)如何实现子程序的调用?其过程是什么?
//TODO
(24)中断类型码、中断向量、中断向量表、中断例程是什么?中断发生时CPU执行过程是什么?
//TODO
先罢工了!!
参考文献
黑色星辰的课件儿
《x86汇编语言-从实模式到保护模式》
翔哥