计算机组成与汇编基础问答详解


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

指令会产生哪两个结果?

首先,相应地调整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

© 版权声明

相关文章

暂无评论

none
暂无评论...