欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > 《汇编语言:基于X86处理器》第3章 复习题和练习,编程练习

《汇编语言:基于X86处理器》第3章 复习题和练习,编程练习

2025/11/13 2:30:58 来源:https://blog.csdn.net/chenyijun/article/details/148771213  浏览:    关键词:《汇编语言:基于X86处理器》第3章 复习题和练习,编程练习

本篇记录《汇编语言:基于X86处理器》第3章 复习题和练习,编程练习的学习。

3.9复习题和练习

3.9.1 简答题

1.举例说明三种不同的指令助记符。

答:MOV,ADD和MUL。

2.什么是调用规范?如何在汇编语言声明中使用它?

答: 在汇编语言中,‌调用规范(Calling Convention)‌ 是定义函数调用过程中参数传递、堆栈管理、寄存器使用和返回值传递等细节的底层规则集。 例如

; 声明内存模型和调用规范(如 stdcall)

.model flat, stdcall ; 32 位平坦内存模型 + stdcall 规范:ml-citation{ref="1" data="citationList"}

3.如何在程序中为堆栈预留空间?

答:.stack 4096

4.说明为什么术语汇编器语言不太正确。

答: 术语“汇编器语言”(assembler language)不太正确,因为它混淆了“汇编语言”(assembly language)与“汇编器”(assembler)工具的区别。

5.说明大端序和小端序之间的区别,并在网络上查找这些术语的起源。

答:大端序和小端序之间的区别是,大小端低位放在高地址,而小端序低位放低地址。

6.为什么在代码中使用符号常量而不是整数常量?

答:使用符号常量会让程序更加容易阅读和维护。设想,如果COUNT在整个程序中出现多次,那么在之后的时间里,程序员就能方便地重新定义它的值。

7.源文件与列表文件的区别是什么?

答:列表文件包含了程序源代码的副本,再加上行号、偏移地址、翻译的机器代码和符号表,适合打印。

8.数据标号与代码标号的区别是什么?

答:数据标号标记数据位置,代码标号标记代码的位置,并且以(:)号结束。

9.(真/假):标识符不能以数字开头。

答:真。第一个字符必须为字母(A...Z, a...z),下划线(_)、@ 、?或$。其后的字符也可以是数字。

10.(真/假);十六进制常量可以写为0x3A。

答:假。汇编代码里不能写成0x开头的十六进制数,这应该写成3Ah.

11.(真/假):汇编语言伪指令在运行时执行。

答:假。汇编的伪指令在汇编时处理。

12.(真/假):汇编语言伪指令可以写为大写字母和小写字母的任意组合。

答:真

13.说出汇编语言指令的四个基本组成部分。

答:1.标号(可选),2.指令助记符(必需),3.操作数(通常是必需的),4.注释(可选)

14.(真/假):MOV是指令助记符的例子。

答:真

15.(真/假):代码标号后面要跟冒号(:),而数据标号则没有。

答:真

16.给出块注释的例子。

答:COMMENT !

....这里是多行注释

CoMMENT !

17.使用数字地址编写指令来访问变量,为什么不是一个好主意?

答:使用数字地址编写指令来访问变量有这几个问题:可维护性差,可读性低,平台依赖性强,安全性风险高,调试困难。

18.必须向ExitProcess过程传递什么类型的参数?

答:DWORD

19.什么伪指令用来结束子程序?

答:ENDP伪指令用来结束子程序。

20.32位模式下,END伪指令中的标识符有什么用?

答:END伪指令标记一个程序的结束。

21.PROTO伪指令的作用是什么?

答:PROTO伪指令主要用于‌声明函数原型‌,为后续的函数调用提供参数和返回值类型规范

22(真/假):目标文件由链接器生成。

答:假,目标文件由汇编器读取源文件生成。

23.(真/假):列表文件由汇编器生成。

答:真。

24.(真/假):链接库只有在生成可执行文件之前才加到程序中。

答:假。

  • 静态链接库‌:在生成可执行文件之前(编译的链接阶段)被嵌入到程序中,成为可执行文件的一部分,程序可独立运行。
  • 动态链接库‌:在程序运行时(如加载或调用时)才被链接和加载到内存中,而非在生成可执行文件之前添加。动态链接库允许内存共享和按需加载,避免了静态链接的冗余拷贝问题

25.哪个数据伪指令定义32位有符号整数变量?

答:SDWORD,例如:val SDWORD ?

26.哪个数据伪指令定义16位有符号整数变量?

答:WORD,例如:val WORD ?

27.哪个数据伪指令定义64位无符号整数变量?

答:SQWORD,例如:val SQWORD ?

28.哪个数据伪指令定义8位有符号整数变量?

答:QWORD,例如:val QWORD ?

29.哪个数据伪指令定义10字节压缩BCD变量?

答:TBYTE, 例如:val TBYTE ?

3.9.2 算法基础

答:val1 EQU 25

val2 EQU 0001 1001b

val3 EQU 31o

val4 EQU 19h

2.通过实验和错误,找出一个程序是否能有多个代码段和数据段。

答:通过实现,一个程序可以有多个代码段和数据段,例如:

;3.9.2_2.asm   第3章 3.9.2算法基础 第2题 验证.386
.model flat, stdcall 
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
sum DWORD 0.data
res SDWORD 0.code
start PROCmov bx, 7add bx, 8
start ENDP.code
main PROCmov eax, 5add eax, 6mov sum, eax INVOKE ExitProcess, 0
main ENDP
END main

3.编写数据定义,把一个双字按大端序存放在内存中。

;3.9.2_3.asm   第3章 3.9.2算法基础 第3题 编写数据定义,把一个双字按大端序存放在内存中。.386
.model flat, stdcall 
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
;big_endian_value db 0xA1, 0xB2, 0xC3, 0xD4
LittleEndianDWORD DWORD 12345678h.code
main PROCmov eax, dword ptr [LittleEndianDWORD]  ; 加载原始值mov ebx, 0                              ; 初始化目标值mov edx, eax                            ; 提取最低有效字节shl edx, 24                             ; 移动到最高有效字节位置or ebx, edx                             ; 合并到目标值 此时bx=78000000hmov edx, 0mov dl, byte ptr [LittleEndianDWORD+1]  ;edx=00000056hshl edx,16                              ;edx=005600hor ebx,edx                              ;ebx=78560000hmov edx, 0mov dl, byte ptr [littleEndianDWORD+2]  ;edx=00000034hshl edx, 8                              ;edx=00003400hor ebx, edx                             ;ebx=78563400hmov edx, 0mov dl, byte ptr [littleEndianDWORD+3]  ;edx=00000012hor ebx, edx                             ;ebx=78563412hmov dword ptr [littleEndianDWORD], ebx  ; 将结果存储到内存地址 littleEndianDWORDmov eax, dword ptr [LittleEndianDWORD]  ; 查看修改后的值 INVOKE ExitProcess, 0
main ENDP
END main

运行调试:调试前:

调试后:

内存中的数据由12345678h转换成78563412h

4.试发现用 DWORD 类型定义一个变量时,是否能向其赋予负数值。这说明了汇编器类型检查的什么问题?

;3.9.2_4.asm   第3章 3.9.2 算法基础 第4题 试发现用 DWORD 类型定义一个变量时,是否能向其赋予负数值。这说明了汇编器类型检查的什么问题?.386
.model flat, stdcall 
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
sum DWORD -3		;初始化为一个负数.code
main PROCmov eax, 5add eax, 6mov sum, eax INVOKE ExitProcess, 0
main ENDP
END main

运行调试:

说明汇编器检查数据是,如果是负数会转成补码。

5.编写一个程序,包含两条指令:(1)EAX寄存器加5;(2)EDX寄存器加5。生成列表文件并检查由汇编器生成的机器代码。发现这两条指令的不同之处了吗?如果有,是什么?

;3.9.2_5.asm   第3章 3.9.2 算法基础 第5题 编写一个程序,包含两条指令:(1)EAX寄存器加5;(2)EDX寄存器加5。
;生成列表文件并检查由汇编器生成的机器代码。发现这两条指令的不同之处了吗?如果有,是什么?.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
sum DWORD 0
sum2 DWORD 0.code 
main PROCmov eax, 0add eax, 5mov sum, eax mov edx, 0add edx, 5mov sum2, edxINVOKE ExitProcess, 0
main ENDP
END main

列表文件

Microsoft (R) Macro Assembler Version 14.41.34120.0	    06/20/25 16:23:54
3.9.2_5.asm						     Page 1 - 1;3.9.2_5.asm   第3章 3.9.2 算法基础 第5题 编写一个程序,包含两条指令:(1)EAX寄存器加5;(2)EDX寄存器加5。;生成列表文件并检查由汇编器生成的机器代码。发现这两条指令的不同之处了吗?如果有,是什么?.386.model flat, stdcall.stack 4096ExitProcess PROTO, dwExitCode:DWORD00000000											.data00000000 00000000						sum DWORD 000000004 00000000						sum2 DWORD 000000000											.code 00000000											main PROC00000000  B8 00000000				mov eax, 000000005  83 C0 05						add eax, 500000008  A3 00000000 R			mov sum, eax 0000000D  BA 00000000				mov edx, 000000012  83 C2 05						add edx, 500000015  89 15 00000004 R		mov sum2, edxINVOKE ExitProcess, 00000001B  6A 00	   *	    	push   +000000000h0000001D  E8 00000000 E   *	    call   ExitProcess00000022			main ENDPEND mainMicrosoft (R) Macro Assembler Version 14.41.34120.0	    06/20/25 16:23:54
3.9.2_5.asm						     Symbols 2 - 1Segments and Groups:N a m e                 Size     Length   Align   Combine ClassFLAT . . . . . . . . . . . . . .	GROUP
STACK  . . . . . . . . . . . . .	32 Bit	 00001000 DWord	  Stack	  'STACK'	 
_DATA  . . . . . . . . . . . . .	32 Bit	 00000008 DWord	  Public  'DATA'	
_TEXT  . . . . . . . . . . . . .	32 Bit	 00000022 DWord	  Public  'CODE'	Procedures, parameters, and locals:N a m e                 Type     Value    AttrExitProcess  . . . . . . . . . .	P Near	 00000000 FLAT	Length= 00000000 External STDCALL
main . . . . . . . . . . . . . .	P Near	 00000000 _TEXT	Length= 00000022 Public STDCALLSymbols:N a m e                 Type     Value    Attr@CodeSize  . . . . . . . . . . .	Number	 00000000h   
@DataSize  . . . . . . . . . . .	Number	 00000000h   
@Interface . . . . . . . . . . .	Number	 00000003h   
@Model . . . . . . . . . . . . .	Number	 00000007h   
@code  . . . . . . . . . . . . .	Text   	 _TEXT
@data  . . . . . . . . . . . . .	Text   	 FLAT
@fardata?  . . . . . . . . . . .	Text   	 FLAT
@fardata . . . . . . . . . . . .	Text   	 FLAT
@stack . . . . . . . . . . . . .	Text   	 FLAT
sum2 . . . . . . . . . . . . . .	DWord	 00000004 _DATA	
sum  . . . . . . . . . . . . . .	DWord	 00000000 _DATA	0 Warnings0 Errors

同样是加法操作,生成的机器码不一样

6.假设有数值456789ABh,按小端序列出其字节内容。

答:小端序是低位存放在低地址,因此列出字节的内容为:0A8h, 89h, 67h, 45h.

7.声明一个数组,其中包含 120个未初始化无符号双字数值。

答:val sdword 120 dup(?)

8.声明一个字节数组,并将其初始化为字母表的前5个字母。

答:myArray byte 'a', 'b', 'c', 'd', 'e'

9.声明一个 32 位有符号整数变量,并初始化为尽可能小的十进制负数。(提示:参阅第1 章的整数范围。

答:minNegative32 DWORD -2147483648 ; 声明并初始化为最小的 32 位有符号整数

10.声明一个 16 位无符号整数变量 wArray,使其具有 3 个初始值。

答:wArray SWORD 10, 20, 30

11.声明一个字符串变量,包含你最喜欢颜色的名字,并将其初始化为空字节结束的字符串。

答:myColor BYTE "blue", 0

12.声明一个未初始化数组dArray,包含50个有符号双字。

答:myArray DWORD 50 dup(?)

13.声明一个字符串变量,包含单词“TEST”并重复500次。

答:myString BYTE 500 dup("TEST")

14.声明一个数组 bArray,包含 20个无符号字节,并将其所有元素都初始化为 0。

答:bArray SBYTE 20 dup(0)

15.写出下述双字变量在内存中的字节序列(从最低字节到最高字节);

val1 DWORD 87654321h

答:x86处理器在内存中按小端序存放数据,因此从最低字节到最高字节的序列为:21h, 43h, 65h, 87h。

3.10 编程练习

*1.整数表达式的计算

参考 3.2 节的程序 AddTwo,编写程序,利用寄存器计算表达式:A-(A+B)-(C-D)。整数值分配给寄存器 EAX、EBX、ECX 和EDX。

;3.10_1.asm 第3章 编程练习   *1.整数表达式的计算  
;参考 3.2 节的程序 AddTwo,编写程序,利用寄存器计算表达式:A-(A+B)-(C-D)。
;整数值分配给寄存器 EAX、EBX、ECX 和EDX。.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
sum DWORD 0.code
main PROCmov eax, 10mov ebx, 5mov ecx, 6mov edx, 15add ebx, eax	;ebx = (A + B)sub eax, ebx	;eax = A - (A + B)sub ecx, edx	;ecx = C - D sub eax, ecx	;eax = A - (A + B) - (C - D)mov sum, eaxINVOKE ExitProcess, 0
main ENDP
END main

结果:10-(10+5)-(6-15)= 4

运行结果:

*2.符号整数常量

编写程序,为一周七天定义符号常量。创建一个数组变量,用这些符号常量作为其初始值。

;3.10_2.asm 第3章 编程练习  *2.符号整数常量  
;编写程序,为一周七天定义符号常量。创建一个数组变量,用这些符号常量作为其初始值。 .386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
Monday		EQU 1			;星期一
Tuesday		EQU 2			;星期二
Wednesday	EQU 3			;星期三
Thursday	EQU 4			;星期四
Friday		EQU 5			;星期五
Saturday	EQU 6			;星期六
Sumday		EQU 7			;星期日WorkdayArray DWORD Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sumday.code
main PROCmov eax, [WorkdayArray]			mov ebx, [WorkdayArray+4]		;一个数占32位,4个字节,如果WorkdayArray定义的是BYTE,这里都是加1mov ecx, [WorkdayArray+8]mov edx, [WorkdayArray+12]INVOKE ExitProcess, 0
main ENDP
END main

运行测试:

**3.数据定义

编写程序,对 3.4 节表 3-2 中列出的每一个数据类型进行定义,并将每个变量都初始化为与其类型一致的数值。

;3.10_3.asm 第3章 数据定义  
;编写程序,对 3.4 节表 3-2 中列出的每一个数据类型进行定义,
;并将每个变量都初始化为与其类型一致的数值。.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
val1	BYTE 0						;最小的无符号数,8位无符号整数,B代表字节 
val2	SBYTE -128					;最小的有符号数,8位有符号整数,S代表有符号
val3	WORD 0						;最小的无符号数,16位无符号整数 
val4	SWORD -32768				;最小的有符号数,16位有符号整数
val5	DWORD 0						;最小的无符号数,32位无符号整数,D代表双(字)
val6	SDWORD -2147483648			;最小的有符号数,32位有符号整数,SD代表有符号双(字)
val7	FWORD 1234567890h			;48位整数(保护模式中的远指针)
val8	QWORD 1234567812345678h		;64位整数,Q代表四(字)
val9	TBYTE 11223344556677889900h;80位(10字节)整数,T代表10字节
val10	REAL4 5.6					;32位(4字节)IEEE短实数
val11	REAL8 3.2E-260				;64位(8字节)IEEE长实数
val12	REAL10 4.6E+4096			;80位(10字节)IEEE扩展实数.code
main PROCmov eax, val5mov ebx, val6INVOKE ExitProcess, 0
main ENDP
END main

运行调试:

*4.符号文本常量

编写程序,定义几个字符串文本(引号之间的字符)的符号名称,并将每个符号名称都用于变量定义。

;3.10_4.asm   第3章   *4.符号文本常量   
;编写程序,定义几个字符串文本(引号之间的字符)的符号名称,并将每个符号名称都用于变量定义。.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD.data
constStr1 TEXTEQU <"this is a string",0>
myString1 BYTE constStr1
constStr2 TEXTEQU <"aaaa is a string",0>
myString2 BYTE constStr2.code
main PROCmov eax, 5mov ebx, DWORD PTR [myString2]INVOKE ExitProcess, 0
main ENDP
END main

运行调试:

*****5.AddTwoSum 的列表文件

生成 AddTwoSum 程序的列表文件,为每条指令的机器代码字节编写说明。某些字节值的含义可能需要猜测。

;3.10_5.asm   第3章 *****5.AddTwoSum 的列表文件
;生成 AddTwoSum 程序的列表文件,为每条指令的机器代码字节编写说明。
;某些字节值的含义可能需要猜测。.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD.data
sum DWORD 0.code
main PROC mov eax, 5add eax, 6mov sum, eaxINVOKE ExitProcess,0
main ENDP
END main

列表文件:

Microsoft (R) Macro Assembler Version 14.41.34120.0	    06/20/25 23:38:06
3.10_5.asm						     Page 1 - 1;3.10_5.asm   第3章 *****5.AddTwoSum 的列表文件;生成 AddTwoSum 程序的列表文件,为每条指令的机器代码字节编写说明。;某些字节值的含义可能需要猜测。.386																			; 32位指令集标识符(机器码无直接对应).model flat,stdcall												; 内存模式声明(伪指令无机器码).stack 4096																; 栈空间声明(伪指令无机器码)ExitProcess PROTO,dwExitCode:DWORD				; 函数原型声明(伪指令)00000000			.data00000000 00000000		sum DWORD 0									; 变量定义(机器码: 00 00 00 00)00000000			.code00000000			main PROC 00000000  B8 00000005				mov eax, 5						; B8: MOV指令 opcode,  05 00 00 00: 立即数5(小端序)00000005  83 C0 06						add eax, 6						; 83 C0: ADD指令 opcode+modrm,   06: 立即数600000008  A3 00000000 R			mov sum, eax					; A3: MOV指令 opcode,   00 00 00 00: sum地址(需链接时确定)INVOKE ExitProcess,00000000D  6A 00	   *	    		push   +000000000h	; 6A: PUSH立即数 opcode0000000F  E8 00000000 E   *	  call   ExitProcess	; E8: CALL相对地址(需重定位)00000014									main ENDPEND mainMicrosoft (R) Macro Assembler Version 14.41.34120.0	    06/20/25 23:38:06
3.10_5.asm						     Symbols 2 - 1Segments and Groups:N a m e                 Size     Length   Align   Combine ClassFLAT . . . . . . . . . . . . . .	GROUP
STACK  . . . . . . . . . . . . .	32 Bit	 00001000 DWord	  Stack	  'STACK'	 
_DATA  . . . . . . . . . . . . .	32 Bit	 00000004 DWord	  Public  'DATA'	
_TEXT  . . . . . . . . . . . . .	32 Bit	 00000014 DWord	  Public  'CODE'	Procedures, parameters, and locals:N a m e                 Type     Value    AttrExitProcess  . . . . . . . . . .	P Near	 00000000 FLAT	Length= 00000000 External STDCALL
main . . . . . . . . . . . . . .	P Near	 00000000 _TEXT	Length= 00000014 Public STDCALLSymbols:N a m e                 Type     Value    Attr@CodeSize  . . . . . . . . . . .	Number	 00000000h   
@DataSize  . . . . . . . . . . .	Number	 00000000h   
@Interface . . . . . . . . . . .	Number	 00000003h   
@Model . . . . . . . . . . . . .	Number	 00000007h   
@code  . . . . . . . . . . . . .	Text   	 _TEXT
@data  . . . . . . . . . . . . .	Text   	 FLAT
@fardata?  . . . . . . . . . . .	Text   	 FLAT
@fardata . . . . . . . . . . . .	Text   	 FLAT
@stack . . . . . . . . . . . . .	Text   	 FLAT
sum  . . . . . . . . . . . . . .	DWord	 00000000 _DATA	0 Warnings0 Errors

调试对比猜想:

***6.AddVariables 程序

修改 AddVariables 程序使其使用 64 位变量。描述汇编器产生的语法错误,并说明为解决这些错误采取的措施。

答:修改相应变量后,编译报错:

根据错误提示,修改相关代码:

去掉这3行

.386
.model flat, stdcall
.stack 4096

把 ExitProcess PROTO, dwExitCode:DWORD 改成 ExitProcess PROTO

把 INVOKE ExitProcess, 0 改成 call ExitProcess

把 END main 改成 END

修改后,完整的代码如下

;3.10_6_AddVariables.asm       ***6.AddVariables 程序   
;修改 AddVariables 程序使其使用 64 位变量。描述汇编器产生的语法错误,并说明为解决这些错误采取的措施。ExitProcess PROTO.data
firstval	QWORD 20002000h
secondval	QWORD 11111111h
thirdval	QWORD 22222222h
sum			QWORD 0.code
main PROCmov rax, firstvaladd rax, secondvaladd rax, thirdvalmov sum, raxcall ExitProcess
main ENDP
END

运行调试:

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词