当前位置: 首页 > news >正文

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

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

6.10 复习题和练习

6.10.1 简答题

1.执行下述指令后,BX中的值是多少?

mov bx,0FFFFh

and bx,6Bh

答:BX中的值是6Bh.

2.执行下述指令后,BX中的值是多少?

mov bx,91BAh

and bx,92h

答:BX中的值是92h.

3.执行下述指令后,BX中的值是多少?

mov bx,0649Bh

or bx,3Ah

答:BX中的值是64BBh

4.执行下述指令后,BX中的值是多少?

mov bx, 029D6h

xor bx, 8181h

答:BX中的值是0A857h.

5.执行下述指令后,EBX中的值是多少?

mov ebx,0AFAF649Bh

or ebx,3A219604h

答:EBX中的值是0BFAFF69Fh.

6.执行下述指令后,RBX中的值是多少?

mov rbx,0AFAF649Bh

xor rbx, 0FFFFFFFFh

答:RBX中的值是0FFFFFFFF50509B64h.

完整代码测试笔记:

;6.10.1_1.asm      6.10.1 简答题 1~6题ExitProcess PROTO.code 
main PROC;1.执行下述指令后,BX中的值是多少?mov bx, 0FFFFhand bx, 6Bh;2.执行下述指令后,BX中的值是多少?mov bx, 91BAhand bx, 92h;3.执行下述指令后,BX中的值是多少?mov bx, 0649Bhor bx, 3Ah;4.执行下述指令后,BX中的值是多少?mov bx, 029D6hxor bx, 8181h;5.执行下述指令后,EBX中的值是多少?mov ebx, 0AFAF649Bhor ebx, 3A219604h				;6.执行下述指令后,RBX中的值是多少?mov rbx, 0AFAF649Bhxor rbx, 0FFFFFFFFhcall ExitProcess
main ENDP 
END 

7.下述指令序列中,写出指定的AL二进制结果值:

mov al, 01101111b
and al, 00101101b				;a. AL = 00101101b = 2Dh
mov al, 6Dh
and al, 4Ah						;b. AL = 01001000b = 48h
mov al, 00001111b
or al, 61h						;c. AL = 01101111b = 6Fh
mov al, 94h	
xor al, 37h						;d. AL = 00101101b = 0A3h

答:调试验证:

8.下述指令序列中,写出指定的AL十六进制结果值:

mov al, 7Ah
not al								;a.  AL = 10000101b = 85h
mov al, 3Dh
and al, 94h							;b.  AL = 00010100b = 14h
mov al, 9Bh
or al, 35h							;c.  AL = 10111111b = 0CFh
mov al, 72h	
xor al, 0DCh						;d.  AL = 11001000b = 0C8h

答:调试验证:

9.下述指令序列中,写出指定的进位标志位、零标志位和符号标志位的值:

mov al, 00001111b
test al, 00000001b			;a. CF=0 ZF=0 SF=0
mov al, 00000110b
cmp al, 00000101b			;b. CF=0 ZF=0 SF=0		
mov al, 00000101b	
cmp al, 00000111b			;c. CF=1 ZF=0 SF=1	

答:调试验证:

10.哪条条件跳转指令根据 ECX的内容执行分支?

答:ECXZ(Jump if ECX is Zero) 是专门根据 ECX 寄存器内容执行分支的条件跳转指令

11.JA和JNBE指令是如何受到零标志位和进位标志位的影响的?

答:JA/JNBE 会在满足以下条件时跳转:

CF = 0且ZF = 0(无进位且结果不为零)

标志位含义

  1. CF = 0
  • 表示无符号比较时,第一个操作数不小于第二个操作数(即 ≥)。
  • 如果 CF=1,说明发生了借位(第一个操作数 < 第二个操作数),此时不跳转。
  1. ZF = 0
  • 表示两个操作数不相等
  • 如果 ZF=1,说明两数相等(结果为零),此时不跳转。

12.执行下述代码后,EDX的最终值是多少?

    mov edx, 1mov eax, 7FFFhcmp eax, 8000hjl L1			(jl是有符号数比较,-1, 小于跳转)	mov edx, 0
L1:

答:EDX的最终值是1

13.执行下述代码后,EDX的最终值是多少?

    mov edx, 1mov eax, 7FFFhcmp eax, 8000h jb L1							;jb是无符号数比较,小于跳转)mov edx, 0
L1:

答:EDX的最终值是1

14.执行下述代码后,EDX的最终值是多少?

    mov edx, 1mov eax, 7FFFhcmp eax, 0FFFF8000hjl L2									;jl是有符号数比较,小于跳转			mov edx, 0
L2:

答:EDX的最终值是0

15.(真/假):下述代码将跳转到标号Target。

mov eax, -30
cmp eax, -50
jg Target    ;有符号比较,大于跳转		cmp结果为20

答:真

16.(真/假):下述代码将跳转到标号 Target。

mov eax,-42
cmp eax, 26
ja Target     ;无符号比较,大于跳转  cmp结果为正

答:真

17.执行下列指令后,RBX的值是多少?

mov rbx, 0FFFFFFFFFFFFFFFFh

and rbx,80h

答:RBX的值是80h

18.执行下列指令后,RBX的值是多少?

mov rbx, 0FFFFFFFFFFFFFFFFh

and rbx, 808080h

答:RBX的值是808080h

19.执行下列指令后,RBX的值是多少?

mov rbx, 0FFFFFFFFFFFFFFFFh

and rbx, 80808080h

答:RBX的值是80808080h

这个验证结果是这样子,不得其解??????

6.10.2 算法基础

1.编写一条指令将 AL 中的 ASCII 数字转换为相应的二进制数。如果 AL包含的已经是二进制(00h~ 09h),则不进行转换。

;6.10.2_1.asm      6.10.2 算法基础  
;1.编写一条指令将 AL 中的 ASCII 数字转换为相应的二进制数。如果 AL包含的已经是二进制(00h~ 09h),则不进行转换。.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD.code 
main PROCmov al, '5'					;测试值cmp al, 30hjb	L1						;小于跳转到L1cmp al, 39hja L1						;大于跳转到L1sub al, 30h					;转换指令	nop
L1:INVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

2.编写指令计算 32 位内存操作数的奇偶性。提示:使用本节之前给出的公式:B0 XOR B1 XOR B2 XOR B3。

;6.10.2_2.asm      6.10.2 算法基础  
;2.编写指令计算 32 位内存操作数的奇偶性。提示:使用本节之前给出的公式:B0 XOR B1 XOR B2 XOR B3。.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD.code 
main PROCmov eax, 57573535h					;测试值mov bx, ax							;把低16位给bx,即B2和B3字节shr eax, 16							;ax为高16位,即B0和B1字节xor ah, al							;B0 XOR B1xor ah, bh							;B0 XOR B1 XOR B2xor ah, bl							;B0 XOR B1 XOR B2 XOR B3nopINVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

3.设有两个位映射集SetX和SetY,编写指令序列在EAX中生成一个位串,以表示属于SetX但不属于SetY的元素。

;6.10.2_3.asm      6.10.2 算法基础  
;3.设有两个位映射集SetX和SetY,编写指令序列在EAX中生成一个位串,以表示属于SetX但不属于SetY的元素。INCLUDE Irvine32.inc.data
SetX DWORD 873B2A53h
SetY DWORD 29C7D7A5h.code 
main PROCmov eax, SetX			mov edx, SetYnot edx						;对SetY取反,得到所有不属于SetY的位and eax, edx				;EAX = SetX AND (NOT SetY);显示二进制字符串mov ebx, TYPE DWORDcall WriteBinBcall CrlfINVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

4.编写指令,若DX中的无符号数小于等于CX中的数,则跳转到标号L1。

;6.10.2_4.asm      6.10.2 算法基础  
;4.编写指令,若DX中的无符号数小于等于CX中的数,则跳转到标号L1。.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD.code 
main PROCmov ax, 9mov dx, 12					;测试值mov cx, 35					;测试值cmp dx, cxjbe	L1						;无符号小于或等于跳转到L1	mov ax, 1
L1:INVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

5.编写指令,若AX中的有符号数大于CX中的数,则跳转到标号 L2。

;6.10.2_5.asm      6.10.2 算法基础  
;5.编写指令,若AX中的有符号数大于CX中的数,则跳转到标号 L2。.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD.code 
main PROCmov ax, 55					;测试值mov cx, 23					;测试值cmp ax, cxjg L2						;有符号数大于跳转到L2mov ax, 99	
L2:	nopINVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

6.编写指令,清除 AL的位0和位1,若目的操作数等于零,则代码跳转到标号L3;否则跳转到标号L4。

;6.10.2_6.asm      6.10.2 算法基础  
;6.编写指令,清除 AL的位0和位1,若目的操作数等于零,则代码跳转到标号L3;否则跳转到标号L4。.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.code 
main PROCmov al, 9				;测试值and al, 1100b			;清除AL的位0和位1jz L3					;为0跳转到L3jnz L4					;否则不为0跳转到L4jmp quit
L3:	mov ebx, 8jmp quit
L4:	mov ebx, 9
quit:	nopINVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

7.汇编语言实现下面的伪代码。使用短路求值,并假设val1和X是32位变量。

;6.10.2_7.asm      6.10.2 算法基础  
;7.汇编语言实现下面的伪代码。使用短路求值,并假设val1和X是32位变量。
;if(va11 > ecx) AND (ecx > edx)
;  X = 1;
;else
;  X= 2;.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
val1 DWORD 12
X DWORD 0.code 
main PROCmov eax, val1mov ecx, 10mov edx, 9cmp eax, ecxjbe L1					;小于等跳转到L1cmp ecx, edxjbe L1					;小于等跳转到L1mov X, 1jmp quit
L1:	mov X, 2
quit:	nopINVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

8.汇编语言实现下面的伪代码。使用短路求值,并假设x是32位变量。

;6.10.2_8.asm      6.10.2 算法基础  
;8.汇编语言实现下面的伪代码。使用短路求值,并假设x是32位变量。
;if(ebx > ecx)OR(ebx > va11)
;  X = 1
;else
;  X = 2.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD.data
X DWORD 0
val1 DWORD 10.code 
main PROCmov eax, val1					;测试值mov ebx, 20mov ecx, 30cmp ebx, ecxja L1							;大于跳转到L1cmp ebx, eaxja L1mov X, 2jmp quit
L1:	mov X,1					 
quit:		nopINVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

9.汇编语言实现下面的伪代码。使用短路求值,并假设X是32位变量.

;6.10.2_9.asm      6.10.2 算法基础  
;9.汇编语言实现下面的伪代码。使用短路求值,并假设X是32位变量.
;if(ebx > ecx AND ebx > edx) OR (edx > eax)
;  X = 1
;else
;  X = 2.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD.data
X DWORD 0.code 
main PROCmov eax, 10				;测试值mov ebx, 20mov ecx, 30mov edx, 40cmp edx, eaxja L1					;大于跳转到L1cmp ebx, ecxjbe L2					;小于等于跳转到L2cmp ebx, edxja L1					;大于跳转到L1
L2:mov X, 2	jmp quit
L1:	mov X, 1
quit:	nopINVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

10.汇编语言实现下面的伪代码。使用短路求值,并假设A、B和N是32位有符号数。

;6.10.2_10.asm      6.10.2 算法基础  
;10.汇编语言实现下面的伪代码。使用短路求值,并假设A、B和N是32位有符号数。
;while N>0 
;if N!=3 AND (N<A OR N>B) 
;  N = N-2
;else
;  N=N-1
;end while.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD.data
N DWORD 20
A DWORD 3
B DWORD 5.code 
main PROC.WHILE N > 0mov eax, N          	;不能直接比较两个内存变量.IF ((N != 3) && (eax < A || eax > B))sub N, 2           ;N = N -2.ELSEdec N              ;N = N - 1.ENDIF.ENDWINVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

6.11 编程练习

●第一次测试程序时,总是用调试器进行单步执行。小细节是很容易被遗忘的,调试器可以让程序员看到实际发生了什么。

●若说明要求使用有符号数组,需确保其中包含一个负数值。

●如果指定了输人数值的范围,则测试数据应包括大于上界、在界限中和低于下界的数值。

●使用不同长度的数组,创建多个测试案例。

●当编写的程序要向数组进行写入操作时,Visual Studio调试器是评估程序正确性的最好工具。C使用调试器的 Memory窗口显示数组,可以选择为十六进制或十进制形式。

●调用被测试过程之后,应立刻再次调用该过程以检查其是否保存了所有的寄存器。示例如下:

mov esi, OFFSET array
mov ecx,count
call CalcSum		;用EAX返回和数
cal1 CalcSum		;再次调用,检查寄存器是否已保存

一般EAX中会有一个返回值,因此,EAX当然是无法保存的。所以,通常不能用EAX输人参数。

●如果打算向过程传递多个数组,则应确保不在过程中引用数组名。取而代之,在调用过程之前,将数组偏移量送入ESI或EDI。这就意味着在过程内应使用间接寻址(形如[esi]或[edi])。

●如果需要定义只用于过程内的变量,可以在变量的前面使用.data伪指令,然后在其后使用.code 伪指令。示例如下:

MyCoolProcedure PROC
.data
sum SDWORD?
.codemov sum,0(etc.)

和C++或Java语言中的局部变量不同,该变量仍然全局可见。不过,既然该变量是在过程内定义的,显然不打算在其他的位置使用。当然,必须使用运行时指令来初始化过程内使用变量,因为过程将会被调用多次。再次调用过程时,不会希望它留有前次调用的任何残留的数值。

6.11.2 习题

*1.填充数组

创建过程,用N个随机数填充一个双字数组,这些数必须包含在从j到k的范围内。调用过程时,传递的参数为:保存数据的数组指针、N、j和k的值。对该过程的多次调用之间,要保存所有的寄存器值。编写测试程序,用不同的j和k值两次调用该过程。利用调试器检验结果。

**2.指定范围内的数组元素求和

创建过程,返回从j~k范围(包含)内所有数组元素之和。编写测试程序调用该过程两次需传递的参数为:有符号双字数组指针、数组大小、和k的值。寄存器EAX返回和数。调用过程之间,保存其他所有的寄存器。

**3.计算考试得分

创建过程 CalcGrade,接收0~100范围内的一个整数,并用AL寄存器返回一个大写字母。对该过程的多次调用之间,保存其他所有的寄存器。按照如下规则确定返回字母:

分数范围

等级字母

90~100

A

80~89

B

70~79

C

60~69

D

0~59

F

编写测试程序,在50~100范围内生成10个随机数。每次生成一个整数,并将其传递给CalcGrade过程。可以使用调试器测试程序,另外,如果选择使用本书的链接库,也可以显示每个整数及其对应的等级字母。(本程序要求用Irvine32链接库,因为它要使用RandomRange 过程。)

**4.大学注册

以6.7.3节的大学注册示例为基础,实现下述功能:

●用CMP和条件跳转指令重新编码(取代.F和.ELSEIF伪指令)。

●实现对学分值的范围检查:学分不能小于1也不能大于30。如果发现无效输人,则显示适当的错误消息。

●提示用户输人平均成绩和学分值。

●显示消息给出评估结果,如“The student canregister”或“The student cannot register”(本程序要求使用 Irvine32 链接库。)

***5.布尔计算器(1)

创建程序,其功能为简单的32位整数布尔运算器。显示菜单提示用户从下表中选择一项。

1.x AND y

2.x OR y

3.NOT x

4.x XOR y

5.Exit program(退出程序)

用户做出选择后,调用过程显示将要执行操作的名称。必须用6.5.4节给出的表驱动选择技术实现该过程。(习题6将实现运算操作。)(本程序要求使用Irvine32链接库。)

***6.布尔计算器(2)

继续编写习题5的程序,实现如下过程:

●AND_op:提示用户输人两个十六进制整数。对其进行AND操作,并用十六进制形式显示结果。

●OR_op:提示用户输入两个十六进制整数。对其进行 OR操作,并用十六进制形式显示结果

●NOT_op:提示用户输入一个十六进制整数。对其进行NOT操作,并用十六进制形式显示结果。

●XOR_op:提示用户输人两个十六进制整数。对其进行异或操作,并用十六进制形式显示结果(本程序要求使用 Irvine32 链接库。)

**7.概率和颜色

编写程序,从3种不同的颜色中随机选择一种用以在屏幕上显示文本。通过循环显示20行文本,每行都随机选择一种颜色。每种颜色出现的概率为:白色=30%,蓝色=10%,绿色=60%。建议:在0~9之间生成一个随机数。如果该数在0~2(包含)之间,则选择白色;如果该数等于3.则选择蓝色:如果该数在4~9(包含)之间,则选择绿色。运行程序10次,对其进行测试。每次运行时,观察文本行颜色的分布是否满足要求的概率。(本程序要求使用Irvine32 链接库。)

***8.消息加密

按要求修改6.3.4节的加密程序:创建包含多个字符的密钥。使用该密钥,通过将密钥与明文相应位进行按位XOR运算,来对明文加密和解密。按需重复使用密钥,直到明文中的全部字节都转换完。例如,假设密钥为“ABXmv#7”,则密钥与明文字节之间的对应如下图所示:

**9.PIN 验证

银行用个人专用识别码(Personal ldentification Number,PIN)对每个客户进行唯一标识。假设银行将用户5位PIN中每一位的可接受数值都限定在指定范围内,下表给出了PIN中从左到右每一位数字的可接受取值范围。由此可见,PIN52413是有效的,而PIN43534是无效的,因为第一个数字不在指定范围内。同样,由于最后一个数字,64532也是无效的。

数字序号

范围

1

5~9

2

2~5

3

4~8

4

1~4

5

3~6

本题任务是创建过程 ValidatePIN:接收一个字节数组指针,该数组包含一个5位的PIN值;定义两个数组保存取值范围的最小值和最大值,并使用这些数值来验证传递给过程的PIN中的每一位数字。如有任何一位数字超出范围,则立刻用EAX寄存器返回该数字的位置(1~5)。如果整个 PIN都是有效的,则用EAX返回0。对该过程的多次调用之间,要保存其他所有寄存器的值编写测试程序,使用有效和无效的字节数组,调用ValidatePIN至少四次。在调试器中运行测试程序,每次调用过程后,验证EAX中的返回值是否有效。另外,如果选择用本书的链接库、也可以在每次过程调用后在控制台上显示“Valid”或“Invalid”。

****10.奇偶性检查

数据传输系统和文件子系统通常依靠计算数据块的奇偶性(偶校验或奇校验)来进行错误检测。本题任务是创建一个过程,如果字节数组为偶校验,则EAX返回True;如果是奇校验,则EAX返回Fase。换句话说,如果计算整个数组中的所有位,则结果将为偶数或奇数。对该过程的多次调用之间,要保存其他所有寄存器的值。编写测试程序,调用该过程两次,每次都向其传递数组指针和数组长度。EAX中的过程返回值应为1(True)或0(False)。测试数据,需创建两个至少包括10字节的数组,一个为偶校验,另一个为奇校验。

提示 本章前面的内容展示了如何通过对字节序列反复使用XOR指令,来确定其奇偶性因此,建议使用循环结构。但要注意的是,由于某些机器指令会影响奇偶标志位,而其他指令不会影响奇偶标志位(查看附录B中的所有指令就能发现这一点)。所以,循环结构中检查奇偶性的代码应小心保存和恢复奇偶标志位的状态,以避免程序代码无意间修改了该标志位。

http://www.lryc.cn/news/580085.html

相关文章:

  • js中的FileReader对象
  • 【网络与系统安全】域类实施模型DTE
  • Java技术深潜:从并发陷阱到云原生突围
  • RabbitMQ用法的6种核心模式全面解析
  • Response对象
  • Qt应用快速启动的重要性:从系统上电到界面渲染的全链路加速实践
  • 数据结构 之 【堆】(堆的概念及结构、大根堆的实现、向上调整法、向下调整法)(C语言实现)
  • 浏览器中的 preview 和 response 的值不一致和精度问题解决
  • Spring Cloud网关与CI文件配置请求安全性对比
  • MySQL/MariaDB数据库主从复制之基于二进制日志的方式
  • 影楼精修-智能修图Agent
  • Python-将多张图片合并成一张图片调整指定区域的颜色选框工具
  • 应急响应靶场——web3 ——知攻善防实验室
  • 【Unity开发】Unity实现glb模型上传到场景中使用功能
  • 秘塔AI搜索的通过Prompt生成互动式网页探索(二)
  • python脚本编程:使用BeautifulSoup爬虫库获取热门单机游戏排行榜
  • Android发展历程
  • 面试版-前端开发核心知识
  • Oracle如何使用序列 Oracle序列使用教程
  • Java 大视界 -- Java 大数据实战:智能安防入侵检测的特征工程与模型融合全解析
  • 硬件嵌入式学习路线大总结(一):C语言与linux。内功心法——从入门到精通,彻底打通你的任督二脉!
  • Java教程——线程池和future
  • Spring Boot 应用启动时,端口 8080 已被其他进程占用,怎么办
  • 批量PDF转换工具,一键转换Word Excel
  • Jenkins 介绍
  • 后端密码加密:守护用户数据的钢铁长城
  • [尚庭公寓]06-Redis快速入门
  • 通过 Ansys Discovery CFD 仿真探索电池冷板概念
  • Excel 如何进行多条件查找或求和?
  • WPF 右键菜单 MenuItem 绑定图片时只显示最后一个 Icon