《汇编语言 基于x86处理器》- 读书笔记 - 第3章-汇编语言基础 - 复习题和练习
- 3.9.1 简答题
- 1. 举例说明三种不同的指令助记符。
- 2. 什么是调用规范?如何在汇编语言声明中使用它?
- 3. 如何在程序中为堆栈预留空间?
- 4. 说明为什么术语 *汇编器语言* 不太正确。
- 5. 说明大端序和小端序之间的区别,并在网络上查找这些术语的起源。
- 6. 为什么在代码中使用符号常量而不是整数常量?
- 7. 源文件与列表文件的区别是什么?
- 8. 数据标号与代码标号的区别是什么?
- 9. (真/假):标识符不能以数字开头。
- 10. (真/假):十六进制常量可以写为0x3A。
- 11. (真/假):汇编语言伪指令在运行时执行
- 12. (真/假):汇编语言伪指令可以写为大写字母和小写字母的任意组合。
- 13. 说出汇编语言指令的四个基本组成部分。
- 14. (真/假):MOV是一个指令助记符。
- 15. (真/假):代码标号后面要跟冒号(:),而数据标号则没有。
- 16. 给出块注释的例子。
- 17. 使用数字地址编写指令来访问变量,为什么不是一个好主意?
- 18. 必须向 ExitProcess 过程传递什么类型的参数?
- 19. 什么伪指令用来结束子程序?
- 20. 32位模式下,END伪指令中的标识符有什么用?
- 21. PROTO 伪指令的作用是什么?
- 22. (真/假):目标文件由链接器生成。
- 23. (真/假):列表文件由汇编器生成。
- 24. (真/假):链接库只有在生成可执行文件之前才加到程序中。
- 25. 哪个数据伪指令定义32位有符号整数变量?
- 26. 哪个数据伪指令定义16位有符号整数变量?
- 27. 哪个数据伪指令定义 64位无符号整数变量?
- 28. 哪个数据伪指令定义8位有符号整数变量?
- 29. 哪个数据伪指令定义10字节压缩BCD变量?
- 3.9.2 算法基础
- 1. 定义4个符号常量分别表示整数 25 的十进制形式、二进制形式、八进制形式和十六进制形式。
- 2. 通过实验和错误,找出一个程序是否能有多个代码段和数据段。
- 3. 编写数据定义,把一个双字按大端序存放在内存中。
- 4. 试发现用 DWORD 类型定义一个变量时,是否能向其赋予负数值。这说明了汇编器类型检查的什么问题?
- 5. 编写一个程序,包含两条指令:(1)EAX寄存器加5; (2)EDX寄存器加5。
- 6. 假设有数值 456789ABh,按小端序列出其字节内容。
- 7. 声明一个数组,其中包含120个未初始化无符号双字数值
- 8. 声明一个字节数组,并将其初始化为字母表的前5个字母。
- 9. 声明一个 32位 有符号整数变量,并初始化为尽可能小的十进制负数。(提示:参阅第1章的整数范围。)
- 10. 声明一个 16位无符号整数变量 wArray,使其具有 3 个初始值。
- 11. 声明一个字符串变量,包含你最喜欢颜色的名字,并将其初始化为空字节结束的字符串。
- 12. 声明一个未初始化数组 dArray,包含 50个有符号双字。
- 13. 声明一个字符串变量,包含单词 “TEST” 并重复500次。
- 14. 声明一个数组 bArray,包含 20 个无符号字节,并将其所有元素都初始化为0。
- 15. 写出下述双字变量在内存中的字节序列(从最低字节到最高字节):
3.9.1 简答题
1. 举例说明三种不同的指令助记符。
解:
mov al,10
add al,10
sub al,5
2. 什么是调用规范?如何在汇编语言声明中使用它?
解:调用规范是:关于函数调用的一系列规则和约定。包括:参数传递、堆栈使用、寄存器使用等方面。
.model flat,stdcall ; 指定存内存模式为 flat 子程序调用规范用 stdcall
stdcall(标准调用)常用于Windows API中一些由C语言编写的函数。
3. 如何在程序中为堆栈预留空间?
解:
.stack 4096 ; 声明栈空间4096字节
4. 说明为什么术语 汇编器语言 不太正确。
解:汇编器
是用于将汇编代码转换为机器代码的工具,而汇编语言
才是指这种特定的低级编程语言。
5. 说明大端序和小端序之间的区别,并在网络上查找这些术语的起源。
解:
大端序
将数据
的高位字节
存储在低地址
,低位字节
存储在高地址
;
小端序
将数据
的低位字节
存储在低地址
,高位字节
存储在高地址
。
关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的《格利佛游记》:Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因是因为吃鸡蛋的方式不同:Lilliput的皇帝认为应该从大头吃起,而Blefuscu的皇帝则认为应该从小头吃起。这个其实讽刺当时英国和法国之间持续的冲突。Danny Cohen一位网络协议的开创者,第一次使用这两个术语指代字节顺序,后来就被大家广泛接受。
6. 为什么在代码中使用符号常量而不是整数常量?
解: 见名知意,且便于批量修改。
7. 源文件与列表文件的区别是什么?
解: 源文件
存汇编源码。
列表文件
是源代码的增强版副本,可能包含结构、联合、过程、参数及局部变量的详细信息。有助于调试和优化代码。
8. 数据标号与代码标号的区别是什么?
解: 数据标号
通常用于标识数据
,主要与数据的存储
和引用
相关。
代码标号
标识代码的特定位置
或指令序列
,用于控制程序的流程跳转
和分支
。
9. (真/假):标识符不能以数字开头。
解: 真
首字符必须是字母(A-Z, a-z)、下划线_、@、? 或 $,后续字符可包含数字。
10. (真/假):十六进制常量可以写为0x3A。
解: 假:会报错 error A2206: missing operator in expression
11. (真/假):汇编语言伪指令在运行时执行
解: 假:伪指令作用于汇编阶段
12. (真/假):汇编语言伪指令可以写为大写字母和小写字母的任意组合。
解: 真
13. 说出汇编语言指令的四个基本组成部分。
解: [标号:] 指令助记符 [操作数][;注释]
14. (真/假):MOV是一个指令助记符。
解: 真
15. (真/假):代码标号后面要跟冒号(😃,而数据标号则没有。
解: 真
16. 给出块注释的例子。
解:
COMMENT !我是一行注释。我是第二行注释。
!
17. 使用数字地址编写指令来访问变量,为什么不是一个好主意?
解: 无法见名知意,如果多处使用,后期修改也不便。
18. 必须向 ExitProcess 过程传递什么类型的参数?
解: dword 32位的无符号整数
19. 什么伪指令用来结束子程序?
解: end
20. 32位模式下,END伪指令中的标识符有什么用?
解: 定义程序入口点
21. PROTO 伪指令的作用是什么?
解: 声明函数原型
22. (真/假):目标文件由链接器生成。
解: 真
23. (真/假):列表文件由汇编器生成。
解: 真
24. (真/假):链接库只有在生成可执行文件之前才加到程序中。
解: 真
25. 哪个数据伪指令定义32位有符号整数变量?
解: SDWORD
26. 哪个数据伪指令定义16位有符号整数变量?
解: SWORD
27. 哪个数据伪指令定义 64位无符号整数变量?
解: QWORD
28. 哪个数据伪指令定义8位有符号整数变量?
解: SBYTE
29. 哪个数据伪指令定义10字节压缩BCD变量?
解: REAL10
3.9.2 算法基础
1. 定义4个符号常量分别表示整数 25 的十进制形式、二进制形式、八进制形式和十六进制形式。
解:
dec25 = 25
bin25 = 00011001b
oct25 = 31q
hex25 = 19h
2. 通过实验和错误,找出一个程序是否能有多个代码段和数据段。
解: 能
3. 编写数据定义,把一个双字按大端序存放在内存中。
解:
.386
.model flat,stdcall
.stack 4096ExitProcess proto,dwExitCode:dword.data
num DWORD 12345678h
result DWORD 0.code
main PROCmov edi,0mov ecx,4
s:mov al, BYTE PTR [num + ecx - 1]mov BYTE PTR [result + edi], alinc ediloop sINVOKE ExitProcess,0
main ENDP
END main
4. 试发现用 DWORD 类型定义一个变量时,是否能向其赋予负数值。这说明了汇编器类型检查的什么问题?
解: 汇编器没有报错,可见是不检查符号的。正常的运算也没问题。
但如果后续我们又把它一个无符号数来使用,可能就会出现问题。比如:显示、转换(因为有符号和无符号的处理方式不同)会得到一些莫名其妙的结果。
.386
.model flat,stdcall
.stack 4096ExitProcess proto,dwExitCode:dword.data
num DWORD -1.code
main PROCmov eax,5add eax,numadd eax,numadd eax,numadd eax,numadd eax,numINVOKE ExitProcess,0
main ENDP
END main
5. 编写一个程序,包含两条指令:(1)EAX寄存器加5; (2)EDX寄存器加5。
生成列表文件并检查由汇编器生成的机器代码。发现这两条指令的不同之处了吗?如果有,是什么?
解:机器码不同
00000000 83 C0 05 add eax,500000003 83 C3 05 add ebx,500000006 83 C1 05 add ecx,500000009 83 C2 05 add edx,5
6. 假设有数值 456789ABh,按小端序列出其字节内容。
解:AB 89 67 45
7. 声明一个数组,其中包含120个未初始化无符号双字数值
解:
.data
myArray DWORD 120 DUP (?)
8. 声明一个字节数组,并将其初始化为字母表的前5个字母。
解:
.data
charArray byte "abcde"
9. 声明一个 32位 有符号整数变量,并初始化为尽可能小的十进制负数。(提示:参阅第1章的整数范围。)
解:
nums32 sdword -2147483648 ; -(2^31)
10. 声明一个 16位无符号整数变量 wArray,使其具有 3 个初始值。
解:
wArray word 1234h, 5678h, 9abch
11. 声明一个字符串变量,包含你最喜欢颜色的名字,并将其初始化为空字节结束的字符串。
解:
color byte 'yellow'
12. 声明一个未初始化数组 dArray,包含 50个有符号双字。
解:
dArray SDWORD 50 DUP (?)
13. 声明一个字符串变量,包含单词 “TEST” 并重复500次。
解:
mystr byte 500 DUP ('TEST')
14. 声明一个数组 bArray,包含 20 个无符号字节,并将其所有元素都初始化为0。
解:
bArray byte 20 DUP (0)
15. 写出下述双字变量在内存中的字节序列(从最低字节到最高字节):
va11 DWORD 87654321h
解: 21 43 65 87