1、什么架构组件将内存与CPU连接起来?
总线(Bus)
2、当计算机关机时,程序存储在哪里?
当计算机关机时,程序通常存储在非易失性存储设备中,如硬盘、固态硬盘、U盘等。
3、缓存内存是如何帮助提高整体性能的?
若访问某内存位置,该值的副本会存入缓存。后续快速连续访问该内存位置时,可从缓存(CPU芯片内部)获取数据。
缓存优势
:从缓存读取数据比从主存读取更快。
缓存命中
:请求的数据能在缓存中找到时,系统通过从缓存读取数据来响应请求,可提高性能。
性能提升
:CPU芯片不断增加缓存内存、改进缓存映射策略,以提高整体性能。
4、在C++中,使用int声明的整数占用多少字节?
4字节
5、在英特尔X86 – 64架构中,每个地址可以存储多少字节?
1字节
6、给定32位十六进制数004C4B40₁₆,求:1. 最低有效字节(LSB) 2. 最高有效字节(MSB)
最低有效字节(LSB)是40;2. 最高有效字节(MSB)是00
7、给定32位十六进制数004C4B40₁₆,展示其小端字节序的内存布局,需显示内存中的每个字节。
在小端字节序中,最低有效字节(LSB)存于最低内存地址,最高有效字节(MSB)存于最高内存地址。
该32位十六进制数
004C4B40₁₆
的小端字节序内存布局如下:
地址(十六进制) | 值 |
---|---|
低地址 | 40 |
4B | |
4C | |
高地址 | 00 |
8、以下每个寄存器分别代表多少位:1. al 2. rcx 3. bx 4. edx 5. r11 6. r8b 7. sil 8. r14w
al
:8位
rcx
:64位
bx
:16位
edx
:32位
r11
:64位
r8b
:8位
sil
:8位
r14w
:16位
9、哪个寄存器指向要执行的下一条指令?
rip
寄存器指向要执行的下一条指令,在函数调用和返回的流程中,
call
指令会将64位的
rip
寄存器压入栈并跳转到函数,
ret
指令会从栈中弹出值到
rip
寄存器,从而跳转到
call
之后的行。
10、哪个寄存器指向栈的当前栈顶?
rsp寄存器指向栈的当前栈顶。
11、如果al被设为05₁₆,ax被设为0007₁₆,eax被设为00000020₁₆,rax被设为0000000000000000₁₆,请给出完整rax寄存器的最终完整内容。
0000000000000000₁₆
12、如果rax寄存器被设置为十进制的81,985,529,216,486,895(十六进制的123456789ABCDEF),那么以下寄存器的十六进制内容分别是什么?1. al 2. ax 3. eax 4. rax
al
:EF₁₆
ax
:CDEF₁₆
eax
:89ABCDEF₁₆
rax
:123456789ABCDEF₁₆
13、给出以下各项的取值范围:1. 有符号字节 2. 无符号字节 3. 有符号字 4. 无符号字 5. 有符号双字 6. 无符号双字
有符号字节:-128 到 +127
无符号字节:0 到 255
有符号字:-32768 到 +32767
无符号字:0 到 65535
有符号双字:-2147483648 到 +2147483647
无符号双字:0 到 4294967295
14、给出以下二进制数的十进制值:1. 0000101₂ 2. 0001001₂ 3. 0001101₂ 4. 0010101₂
0000101₂
的十进制值为 5;
0001001₂
的十进制值为 9;
0001101₂
的十进制值为 13;
0010101₂
的十进制值为 21。
15、给出以下十进制数值的十六进制、字节大小、补码表示。注意,需要两位十六进制数字。1. -3₁₀ 2. +11₁₀ 3. -9₁₀ 4. -21₁₀
本题可根据补码计算方法求解。对于正数,其补码等于原码;对于负数,先求其绝对值的二进制表示,再取反加 1 得到补码。
-3₁₀:3 的二进制为
00000011
,取反为
11111100
,加 1 后为
11111101
,十六进制为
FD
;
+11₁₀:11 的二进制为
00001011
,正数补码等于原码,十六进制为
0B
;
-9₁₀:9 的二进制为
00001001
,取反为
11110110
,加 1 后为
11110111
,十六进制为
F7
;
-21₁₀:21 的二进制为
00010101
,取反为
11101010
,加 1 后为
11101011
,十六进制为
EB
。
所以答案依次为
FD
、
0B
、
F7
、
EB
。
16、给出以下双字大小的十六进制补码值对应的十进制值。1. FFFFFFFB₁₆ 2. FFFFFFEA₁₆ 3. FFFFFFF3₁₆ 4. FFFFFFF8₁₆
-5;2. -22;3. -13;4. -8
17、以下哪个十进制数值在二进制中有精确表示?1. 0.1 2. 0.2 3. 0.3 4. 0.4 5. 0.5
5
18、以下每个字符的十六进制 ASCII 码是什么:1. “A” 2. “a” 3. “0” 4. “8” 5. 制表符
"A"
:
0x41
"a"
:
0x61
"0"
:
0x30
"8"
:
0x38
制表符:
0x09
19、本章中使用的汇编器名称是什么?
yasm汇编器
20、在汇编语言程序中,注释是如何标记的?
在汇编语言程序中,分号(
;
)用于标记注释。分号可放在任何位置,包括指令之后,分号后的任何字符都会被汇编器忽略。
21、已初始化数据声明所在的节的名称是什么?
数据节(data section)
22、未初始化数据声明所在的节的名称是什么?
BSS节
23、代码被放置的节的名称是什么?
.text
24、为以下变量及其给定值进行数据声明:1. 字节大小的变量bNum设置为1010;2. 字大小的变量wNum设置为10291;3. 双字大小的变量dwNum设置为2126010;4. 四字大小的变量qwNum设置为10000000000。
1. bNum db 1010
2. wNum dw 10291
3. dwNum dd 2126010
4. qwNum dq 10000000000
25、以下各项的未初始化数据声明是什么:1. 名为 bArr 的 100 个元素的字节数组;2. 名为 wArr 的 3000 个元素的字数组;3. 名为 dwArr 的 200 个元素的双字数组;4. 名为 qArr 的 5000 个元素的四字数组
1. bArr resb 100;
2. wArr resw 3000;
3. dwArr resd 200;
4. qArr resq 5000
26、在文本段中,标志程序开始所需的声明有哪些?
需包含如下声明:global _start _start:
27、汇编器的第一遍处理会执行哪些操作?
第一遍处理的基本操作包括:
创建符号表
展开宏
计算常量表达式
为程序中的所有语句分配地址
处理一些汇编器指令
28、汇编器第二遍扫描执行哪些操作?
汇编器第二遍扫描执行的基本操作
最终生成代码
创建列表文件
(如果有请求)
创建目标文件
详细说明
代码生成
:需要使用符号表检查程序符号并获取相应的地址。
列表文件
:可用于调试目的。
目标文件
:如果没有错误,将在第二遍扫描时创建最终的目标文件。
29、链接器执行哪些操作?
链接器的操作包括:
将较小的解决方案组合成一个可执行单元;
若使用了用户或系统库例程,链接器会包含相应的例程,将目标文件和库例程组合成一个可执行模块,把机器语言代码从每个目标文件复制到一个可执行文件中;
调整可重定位地址,满足外部引用,并将外部引用的最终位置放入代码中。
30、加载器会执行哪些操作?
尝试打开可执行文件(验证其存在性和权限)
读取头部信息
请求操作系统创建新进程
若成功,读取可执行文件的其余部分并加载到内存(由操作系统指定位置)
加载完成后通知操作系统
注意:加载器不运行进程
31、请给出一个常量表达式的例子。
假设常量 BUFF 已定义,指令 mov rax, BUFF+5 中包含一个常量表达式。
32、为确保程序易于调试,汇编和链接步骤中需要什么选项?
-g 限定符
33、continue命令具体有什么作用?
continue
命令用于继续执行程序到下一个断点。
continue <n>
命令同样是继续执行程序到下一个断点,但会跳过
n - 1
次到达断点的情况,可用于快速到达循环的第
n
次迭代。
34、寄存器窗口如何显示?
寄存器窗口默认不显示,可通过选择顶部菜单栏中的“Status → Registers”来查看。
35、调试器启动后,用户如何退出?
使用’quit’或’q’命令可退出调试器。
36、描述设置断点的多种方法。
可以通过在底部窗口的
(gdb)
提示处输入
break <label/addr>
或
b <label/addr>
命令来设置断点,其中
<label/addr>
指标签或地址。
37、从文件中读取调试器命令的调试器命令是什么?
source
38、当 DDD 显示一个绿色箭头指向一条指令时,这意味着什么?
绿色箭头指向的是下一条要执行的指令,即该箭头所指的语句尚未执行。
39、显示当前栈顶值的调试器命令是什么?
x/ug $rsp
40、显示当前栈顶的五个值的调试器命令是什么?
x/5ug $rsp
41、输入一个示例程序,对该程序进行汇编和链接操作,然后执行调试器。在标签“last”处设置断点并执行程序直至该断点。最后根据变量大小输入相应的调试器检查内存命令,交互式验证所执行的计算是否得出了正确的值。
本题为操作步骤描述,需按以下步骤操作:
输入示例程序;
对程序进行汇编和链接操作;
执行调试器;
在标签
last
处设断点并执行程序到该断点;
根据变量大小输入调试器检查内存命令,交互式验证计算结果。
42、创建一个汇编和链接脚本文件,用该脚本对程序进行汇编和链接,确保脚本能正确完成汇编和链接操作。
可创建如下简单的 bash 汇编/链接脚本:
#!/bin/bash
# 简单的汇编/链接脚本。
if [ -z $1 ]; then
echo "Usage: ./asm64 <asmMainFile> (no extension)"
exit
fi
将上述脚本保存为一个文件,例如
asm64
,然后给该文件添加可执行权限:
chmod +x asm64
之后,在终端中运行该脚本并传入汇编主文件(不带扩展名)作为参数,即可完成汇编和链接操作。
43、解释以下两条指令的区别:1. mov rdx, qword [qVar1] 2. mov rdx, qVar1
下面是给定的【文本内容】:
指令
mov rdx, qword [qVar1]
是将内存地址
qVar1
处的8字节(64位)数据传送到寄存器
rdx
中;
指令
mov rdx, qVar1
是将变量
qVar1
的地址传送到寄存器
rdx
中。
44、下面列出的每条指令的源操作数的寻址方式是什么?请用寄存器寻址、立即数寻址、内存寻址或非法指令来回答。指令如下:mov <目的操作数>, <源操作数>;mov ebx, 14;mov ecx, dword [rbx];mov byte [rbx+4], 10;mov 10, rcx;mov dl, ah;mov ax, word [rsi+4];mov cx, word [rbx+rsi];mov ax, byte [rbx]
- `mov ebx, 14`:立即数寻址
- `mov ecx, dword [rbx]`:内存寻址
- `mov byte [rbx+4], 10`:立即数寻址
- `mov 10, rcx`:非法指令
- `mov dl, ah`:寄存器寻址
- `mov ax, word [rsi+4]`:内存寻址
- `mov cx, word [rbx+rsi]`:内存寻址
- `mov ax, byte [rbx]`:内存寻址
45、给定以下变量声明和代码片段:ans1 dd 7 mov rax, 3 mov rbx, ans1 add eax, dword [rbx] 执行后eax寄存器中的值是什么?以十六进制完整寄存器大小显示。
0x0000000A
46、给定以下变量声明和代码片段:list1 dd 2, 3, 4, 5, 6, 7;mov rbx, list1;add rbx, 4;mov eax, dword [rbx];mov edx, dword [list1]。执行后eax和edx寄存器中的值是什么?以十六进制、完整寄存器大小显示答案。
eax寄存器中的值为0x00000003,edx寄存器中的值为0x00000002。
47、给定以下变量声明和代码片段:lst dd 2, 3, 5, 7, 9 mov rsi, 4 mov eax, 1 mov rcx, 2 lp: add eax, dword [lst+rsi] add rsi, 4 loop lp mov ebx, dword [lst] 执行后,eax、ebx、rcx 和 rsi 寄存器中的值是什么?以十六进制、完整寄存器大小显示。注意,要密切关注寄存器大小(32 位与 64 位)。
要得出具体的十六进制值,需逐步分析代码:
初始化寄存器值
:
–
rsi
初始化为 4
–
eax
初始化为 1
–
rcx
初始化为 2
循环操作
:
– 每次循环将
lst
偏移
rsi
处的双字值加到
eax
上
– 然后
rsi
加 4
– 循环共执行 2 次
根据计算,
eax
最终值为:
eax=1+7+9=17eax=1+7+9=17
对应的十六进制为:
0x000000110x00000011
寄存器赋值
:
– 将
lst
处的双字值赋给
ebx
,即
lst
的首元素 2
– 对应的十六进制为:
0x000000020x00000002
循环结束后的寄存器状态
:
–
rcx
在循环结束后为 0
– 对应的十六进制为:
0x000000000x00000000
–
rsi
经两次加 4 后为 12
– 对应的十六进制为:
0x0000000C0x0000000C
最终结果:
eax
为
0x00000011
ebx
为
0x00000002
rcx
为
0x00000000
rsi
为
0x0000000C
48、更新示例程序,以找出数字列表中的最大值、最小值和平均值。使用调试器执行该程序并显示最终结果。创建一个调试器输入文件来展示结果。
需先更新示例程序,添加找出数字列表最大值、最小值和平均值的代码。
接着使用调试器运行该程序,查看并记录最终结果。
最后创建一个调试器输入文件,将结果展示其中。
49、实现一个程序,计算一组正四棱锥中每个正四棱锥的侧总面积(包括底面)和体积。计算出这些值后,程序要找出总面积和体积的最小值、最大值、总和以及平均值。使用调试器执行程序并显示最终结果。创建一个调试器输入文件来展示结果。
可按以下步骤实现该程序:
编写汇编语言程序,先通过循环计算每个正四棱锥的侧总面积和体积,存储在数组中;再用另一个循环找出每个数组的总和、最小值和最大值,最后计算平均值。
公式为:
–
totalSurfaceAreas(n) = aSides(n) * (2*aSides(n)*sSides(n))
–
volumes(n) = (aSides(n)^2 * heights(n)) / 3
且所有数据为无符号值。
使用调试器执行程序,观察并记录最终结果。
创建一个调试器输入文件,将计算得到的总面积和体积的最小值、最大值、总和以及平均值等结果记录其中。
50、创建一个程序来对一个数字列表进行排序。使用以下冒泡排序算法:从列表长度减 1 到 0 遍历变量 i,每次遍历开始时将 swapped 设为 false;从 0 到 i – 1 遍历变量 j,如果列表中索引为 j 的元素大于索引为 j + 1 的元素,交换这两个元素的值,并将 swapped 设为 true;如果 swapped 为 false,则退出外层循环。使用调试器执行该程序并显示最终结果。创建一个调试器输入文件来展示结果。
以下是实现该功能的 Python 代码示例:
lst = [5, 3, 8, 4, 2]
len_lst = len(lst)
for i in range(len_lst - 1, 0, -1):
swapped = False
for j in range(i):
if lst[j] > lst[j + 1]:
tmp = lst[j]
lst[j] = lst[j + 1]
lst[j + 1] = tmp
swapped = True
if not swapped:
break
print("排序后的列表:", lst)
将上述代码保存为一个 Python 文件(例如
sort_program.py
),然后可以使用 Python 调试器(如
pdb
)来执行该程序。要创建调试器输入文件,可以在代码中添加适当的日志记录,将结果输出到文件中。例如:
import pdb
lst = [5, 3, 8, 4, 2]
len_lst = len(lst)
with open('debugger_input.txt', 'w') as f:
def sort_list():
for i in range(len_lst - 1, 0, -1):
swapped = False
for j in range(i):
if lst[j] > lst[j + 1]:
tmp = lst[j]
lst[j] = lst[j + 1]
lst[j + 1] = tmp
swapped = True
if not swapped:
break
pdb.Pdb(stdout=f).runcall(sort_list)
f.write("排序后的列表: " + str(lst))
运行上述代码后,会生成一个名为
debugger_input.txt
的文件,其中包含调试信息和最终的排序结果。
51、哪个寄存器指向栈顶?
rsp寄存器用于指向当前栈顶。
52、执行
push rax
指令会产生哪两个结果?
push rax
首先,相应地调整rsp(rsp – 8);然后,将操作数复制到[rsp]。
53、pop rax 指令从栈中移除多少字节的数据?
8 字节。因为 pop
指令是弹出 64 位操作数,64 位等于 8 字节。
54、给定以下代码片段:mov r10, 1 mov r11, 2 mov r12, 3 push r10 push r11 push r12 pop r10 pop r11 pop r12。执行后 r10、r11 和 r12 寄存器中的值是什么?以十六进制、完整寄存器大小显示答案。
r10 为 `0x0000000000000001`,r11 为 `0x0000000000000002`,r12 为 `0x0000000000000003`
55、给定以下变量声明和代码片段:lst dq 1, 3, 5, 7, 9;mov rsi, 0;mov rcx, 5;lp1: push qword [lst+rsi
8];inc rsi;loop lp1;mov rsi, 0;mov rcx, 5;lp2: pop qword [lst+rsi
8];inc rsi;loop lp2;mov rbx, qword [lst]。解释代码执行后的结果是什么?
代码首先将数组
lst
中的元素依次压入栈中,由于栈是后进先出的数据结构,之后再将栈中的元素依次弹出并放回数组
lst
中,这会使数组
lst
的元素顺序反转,变为
9, 7, 5, 3, 1
。最后将反转后数组的第一个元素(即
9
)存入寄存器
rbx
中。所以执行后,
rbx
寄存器的值为
9
。
56、编写一个程序,判断一个以空字符结尾、代表一个单词的字符串是否为回文。回文是指一个单词正读和反读都相同。例如,“anna”、“civic”、“hannah”、“kayak”和“madam”都是回文。可以通过将字符串中的字符逐个压入栈中,然后从字符串开头开始将栈中的元素与字符串进行比较来实现。使用调试器执行该程序并显示最终结果。创建一个调试器输入文件来展示结果。
以下是实现该功能的Python代码示例:
def is_palindrome(word):
stack = []
for char in word:
stack.append(char)
for char in word:
if char != stack.pop():
return False
return True
word = "anna"
result = is_palindrome(word)
print(f"字符串 '{word}' 是否为回文: {result}")
在Python中没有直接的调试器输入文件概念,但在其他编程语言(如C、C++)中,可按以下步骤操作:
编写代码,例如C语言代码:
#include <stdio.h>
#include <string.h>
int is_palindrome(char *word) {
int len = strlen(word);
char stack[len];
int top = -1;
for (int i = 0; i < len; i++) {
stack[++top] = word[i];
}
for (int i = 0; i < len; i++) {
if (word[i] != stack[top--]) {
return 0;
}
}
return 1;
}
int main() {
char word[] = "anna";
int result = is_palindrome(word);
printf("字符串 '%s' 是否为回文: %s
", word, result ? "是" : "否");
return 0;
}
使用调试器(如GDB),创建一个包含调试命令的输入文件,例如
debug_input.txt
,内容可以是:
file your_program
break main
run
next
... (根据需要添加更多调试命令)
运行调试器并指定输入文件:
gdb -x debug_input.txt
。