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

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

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

9.9复习题和练习

9.9.1 简答题

1.执行字符串原语时,怎样设置方向标志位CF会使变址寄存器反向遍历内存区?

答:STD 指令设置方向标志位置1使变址寄存器反向遍历内存区

2.当重复前缀与STOSW 一起使用时,变址寄存器增加或减少的值是多少?

答:STOSW保存字符串数据:将累加器内容保存到EDI寻址的内存位置,变址寄存器增加或减少的值是WORD型长度,即2个字节。

3.何种使用方式将导致CMPS 指令意义不明?

答:导致CMPS意义不明的主要情况是:未指定操作数大小、未设置方向标志(DF)、或未正确初始化指针寄存器。始终使用明确的后缀(如CMPSB)或显式操作数,并确保ESI/EDI和DF状态符合预期。

4.若方向标志位清零,且SCASB 发现了匹配的字符,则此时EDI指向哪里?

答:EDI指向发现匹配字符的下一个位置。

5.若想通过扫描发现第一次出现在数组中的特定字符,那么最好使用哪种重复前缀?

答:repne ;不相等且ECX>0则重复

6.9.3节Str_trim 过程中的方向标志位应如何设置?

答:STD;方向标志位置1,反向操作,从最后一个位置开始处理。

7.为什么9.3节的Str_trim过程要使用JNE指令?

答:要把匹配到的字符清空。mov BYTE PTR [edi+1], 0 ;插入一个空字节

8.如果目标字符串包含了一个数字,则9.3节的 Str_ucase 过程将出现什么情况?

答:数字不会变化,因此程序作了判断,遇到小写字母才会转换。

9.如果9.3节的Str_length过程使用了SCASB,那么最合适的重复前缀是哪个?

答:repne scasb ;不相等则重复下一个字符

;9.9.1_9.asm     9.9.1 简答题 
;9.如果9.3节的Str_length过程使用了SCASB,那么最合适的重复前缀是哪个?.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD.data
string BYTE "Good night Tom",0.code 
;------------------------------------------
;获取字符串的长度。
;返回值,EAX返回字符串的长度
;------------------------------------------
Str_length PROC USES edi,pString:PTR BYTEmov edi, pString				;指向字符串mov eax, 0						;字符计数器
L1:	cmp BYTE PTR[edi], 0			;字符结束?je L2							;是:退出inc edi							;否:指向下一个字符inc eax							;计数器加1jmp L1							
L2:	ret								
Str_length ENDP
;------------------------------------------
;使用SCASB获取字符串的长度。
;返回值,EAX返回字符串的长度
;------------------------------------------
Str_lengthScasb PROC USES edi,pString:PTR BYTEmov edi, pString				;指向字符串mov al, 0						;检索值0cldrepne scasb						;不相等则重复下一个字符dec edi							;发现字符edi-1mov eax, edisub eax, pString				;偏移值减超始位置ret								
Str_lengthScasb ENDPmain PROCINVOKE Str_length, ADDR stringmov ebx, eaxINVOKE Str_lengthScasb, ADDR stringnopINVOKE ExitProcess, 0
main ENDP 
END main

运行调试验证:

10.如果9.3节的 Str_length 过程使用了 SCASB,那么它将如何计算并返回字符串长度?

答:用匹配值0的位置减去字符串的起始位置,得到字符串的长度赋给eax。

11.若数组包含1024个元素,则对半查找最多需要比较多少次?

答:10次, 2^{10}=1024

12.在9.5节对半查找示例中,其FillAray过程为什么必须用CLD指令清除方向标志位?

答:填充的时候正向填充。否则反向填充会覆盖其他数据。

13.在9.5节的 BinarySearch 过程中,为什么能在不影响结果的情况下删除标号L2的语句?

答:jge L2 语句前面已经做了比较,结果设置相关标志寄存器,所以这里可以不再次做比较

14.在9.5节的 BinarySearch 过程中,什么情况下有可能删除标号L4的语句?

答:把jmp L4改成jmp L1即可。

9.9.2算法基础

1.举例说明32 位模式下的基址-变址操作数。

答:计算数组的和示例

;9.9.2_1.asm    9.9.2算法基础
;1.举例说明32 位模式下的基址-变址操作数。.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
array DWORD 1010h, 2020h, 3030h, 4040h, 5050h.code
main PROCmov esi, OFFSET array		;基址mov ecx, LENGTHOF array		;数组元素个数mov edi, 0					;变址mov eax, 0					;计算数组的和
L1:	add eax, [esi+edi]			;基址+变址add edi, 4					;下一个元素loop L1INVOKE ExitProcess, 0
main ENDP
END main

运行调试:

2.举例说明 32 位模式下的基址-变址-偏移量操作数。

答:

;9.9.2_1.asm    9.9.2算法基础
;1.举例说明32 位模式下的基址-变址操作数。.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
array DWORD 1010h, 2020h, 3030h, 4040h, 5050h
RowSize=($ - array)DWORD 6060h, 7070h, 8080h, 9090h, 0A0A0hDWORD 0B0B0h, 0C0C0h, 0D0D0h, 0E0E0h, 0F0F0h
row = 1
col = 3.code
main PROC;取1行3列的数mov esi, OFFSET array	;基址mov edi, RowSize		;变址;基址+变址+偏移mov eax, [esi + edi*row + col * TYPE DWORD]mov ebx, array[edi*row + col*TYPE DWORD]INVOKE ExitProcess, 0
main ENDP
END main

运行调试:

3.假设一双字二维数组有3个逻辑行和4个逻辑列。编写表达式,用ESI和EDI指向第2行第3列。(行、列都从 0开始编号。)

答:

;9.9.2_3.asm    9.9.2算法基础
;3.假设一双字二维数组有3个逻辑行和4个逻辑列。编写表达式,用ESI和EDI指向第2行第3列。(行、列都从 0开始编号。).386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD
.data
array DWORD 1010h, 2020h, 3030h, 4040h
RowSize=($ - array)DWORD 5050h, 6060h, 7070h, 8080hDWORD 9090h, 0A0A0h, 0B0B0h, 0C0C0h
row = 2
col = 3.code
main PROCmov esi, row * RowSizemov edi, col * TYPE DWORDmov eax, array[esi  + edi]INVOKE ExitProcess, 0
main ENDP
END main

运行调试:

4.编写指令,用 CMPSW 比较两个16 位的数组sourcew 和targetw。

答:

;9.9.2_4.asm    9.9.2算法基础
;4.编写指令,用 CMPSW 比较两个16 位的数组sourcew 和targetw。.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
sourceW WORD 1234h, 5678h, 9ABCh
targetW WORD 1234h, 5678h, 9ABDh.code
main PROCmov esi, OFFSET sourceWmov edi, OFFSET targetWcmpsw						;比较字ja L1						;若sourceW > targetW则跳转;多个字数组比较cld							;方向为正mov ecx, LENGTHOF sourceW	;设置重复计数器repe cmpsw					;相等则重复;REPE前缀重复比较操作,并自动增加ESI和EDI,直到ECX等于0,或者发现了一对不相等的双字。
L1:	nopINVOKE ExitProcess, 0
main ENDP
END main

运行调试:

最后一个数不相等。

5.编写指令,用SCASW 在数组wordArray 中扫描 16 位的数值0100h,并将匹配元素的偏移量复制到EAX 寄存器。

答:

;9.9.2_5.asm    9.9.2算法基础
;5.编写指令,用SCASW 在数组wordArray 中扫描 16 位的数值0100h,并将匹配元素的偏移量复制到EAX 寄存器。.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD.data
wordArray WORD 1234h, 5678h, 0100h, 9ABCh.code 
main PROCmov esi, OFFSET wordArraymov edi, OFFSET wordArraymov ax, 0100hmov ecx, LENGTHOF wordArraycld							;方向为正repne scasw					;不相等则重复jnz quit					;若未发现字会则退出sub edi, 2					;发现扫描数字,edi指向当前位置 mov eax, edisub eax, OFFSET wordArray	;计算偏移值并保存到EAX中
quit:nopINVOKE ExitProcess, 0
main ENDP
END main

运行调试:

6.编写指令序列,用 Str_compare过程判断两个输入字符串中的较大者,并将其输出到控制台窗口。

答:

;9.9.2_6.asm    9.9.2算法基础
;6.编写指令序列,用 Str_compare过程判断两个输入字符串中的较大者,并将其输出到控制台窗口。INCLUDE Irvine32.inc.data
buffer1 BYTE 32 DUP(0)		;输入缓冲区
buffer2 BYTE 32 DUP(0)
byteCount DWORD ?			;定义计数器
msg1 BYTE "Please enter the first string: ",0
msg2 BYTE "Please enter the second string: ",0
msg3 BYTE "string equal ",0.code
;------------------------------------------
;比较两个字符串。
;无返回值,但是零标志位和进位标志位受到的影响与CMP指令相同。
;------------------------------------------
StrCompare PROC USES eax edx esi edi,string1:PTR BYTE,string2:PTR BYTEmov esi, string1mov edi, string2
L1:	mov al, [esi]mov dl, [edi]cmp al, 0						;string1结束?jne L2							;否cmp dl, 0						;是: string2结束?jne L2							;否mov edx, OFFSET msg3jmp L5							;是: 退进出且ZF=1
L2:	inc esi							;inc edi							;指向下一个字符cmp al, dl						;字符相等?je L1							;是:继续ja L3							;buffer1 > buffer2 跳转到L3mov edx, OFFSET buffer2			;buffer1 < buffer2jmp L5
L3: mov edx, OFFSET buffer1
L5:	 call WriteStringret								;否:退出
StrCompare ENDPmain PROCmov edx, OFFSET msg1call WriteStringmov edx, OFFSET buffer1	        ;指向缓冲区mov ecx, SIZEOF buffer1	        ;定义最大字符数call ReadString			        ;输入字会串 字符串存放在edx指向的缓冲区,个数存在eax中mov byteCount, eax		        ;有效字符数call Crlfmov edx, OFFSET msg2call WriteStringmov edx, OFFSET buffer2	        ;指向缓冲区mov ecx, SIZEOF buffer2	        ;定义最大字符数call ReadString			        ;输入字会串 字符串存放在edx指向的缓冲区,个数存在eax中mov byteCount, eax		        ;有效字符数call CrlfINVOKE StrCompare, ADDR buffer1, ADDR buffer2INVOKE ExitProcess, 0
main ENDP
END main

运行调试:

7.说明如何调用 Str_trim 过程,并从一个字符串中删除所有的尾部字符“@”。

答:INVOKE Str_trim, ADDR string, ‘@’

;9.9.2_7.asm    9.9.2算法基础
;7.说明如何调用 Str_trim 过程,并从一个字符串中删除所有的尾部字符“@”。;.386
;.model flat, stdcall
;.stack 4096
;ExitProcess PROTO,dwExitCode:DWORD
INCLUDE Irvine32.inc.data
string_1 BYTE "Hello@@@",0
string_2 BYTE "Hello@World@@@",0
string_3 BYTE "Hello",0
string_4 BYTE "H@$#&@@@",0
string_5 BYTE "@Hello",0.code 
;------------------------------------------
;获取字符串的长度。
;返回值,EAX返回字符串的长度
;------------------------------------------
StrLengthA PROC USES edi,pString:PTR BYTEmov edi, pString				;指向字符串mov eax, 0						;字符计数器
L1:	cmp BYTE PTR[edi], 0			;字符结束?je L2							;是:退出inc edi							;否:指向下一个字符inc eax							;计数器加1jmp L1							
L2:	ret								
StrLengthA ENDP
;------------------------------------------
;显示字符串。
;返回:无
;------------------------------------------
ShowString PROC pString1:PTR BYTEmov edx, pString1call WriteStringcall Crlfret
ShowString ENDP
;------------------------------------------
;从字符串末尾删除所有与给定分隔符匹配的字符。
;返回:无
;------------------------------------------
StrTrim PROC USES eax ecx edi,pStr:PTR BYTE,					;指向字符串char:BYTE						;要移除的字符mov edi, pStr					;准备调用Str_lengthINVOKE StrLengthA, edi			;用EAX返回长度cmp eax, 0						;长度是否为零?je L3							;是:立刻退出mov ecx, eax					;否:ECX=字符串长度dec eaxadd edi, eax					;指向最后一个字符
L1:	mov al, [edi]					;取一个字符cmp al, char					;是否为分隔符?jne L2							;否:插入空字节dec edi							;是:继续后退一个字符loop L1							;直到字符串的第一个字符
L2:	mov BYTE PTR [edi+1], 0			;插入一个空字节
L3:	ret
StrTrim ENDP
main PROCINVOKE StrTrim, ADDR string_1, '@'INVOKE ShowString, ADDR string_1INVOKE StrTrim, ADDR string_2, '@'INVOKE ShowString, ADDR string_2INVOKE StrTrim, ADDR string_3, '@'INVOKE ShowString, ADDR string_3INVOKE StrTrim, ADDR string_4, '@'INVOKE ShowString, ADDR string_4INVOKE StrTrim, ADDR string_5, '@'INVOKE ShowString, ADDR string_5INVOKE ExitProcess, 0
main ENDP 
END main

运行效果:

 

 

 

 

 

 

 

 

 

 

http://www.dtcms.com/a/294269.html

相关文章:

  • Linux内存映射原理
  • 基于MCP架构的LLM-Agent融合—构建AI Agent的技术体系与落地实践
  • day060-zabbix监控各种客户端
  • 力扣MySQL(1)
  • python 字符串常用处理函数
  • Zookeeper学习专栏(七):集群监控与管理
  • 解决代码生成过程虚拟总线信号无法直接传递给自定义总线信号问题的方法
  • Python curl_cffi库详解:从入门到精通
  • Redis能完全保证数据不丢失吗?
  • 基于OpenOCD 的 STM32CubeIDE 开发烧录调试环境搭建 DAPLINK/STLINK
  • 《计算机网络》实验报告六 电子邮件
  • 【轨物方案】分布式光伏电站运维升级智能化系列:老电站的数智化重生
  • Zabbix 企业级分布式监控
  • Axios 响应拦截器
  • dfaews
  • vue3笔记(2)自用
  • 设备虚拟化技术
  • 筛选数据-group_concat
  • Go语言实现对象存储——下载任意图片,保存到阿里云存储,并将URL保存到数据库。
  • 【数据库】国产数据库的新机遇:电科金仓以融合技术同步全球竞争
  • Pycaita二次开发基础代码解析:图层管理、基准控制与特征解析深度剖析
  • lwIP学习记录5——裸机lwIP工程学习后的总结
  • 【C++】类和对象(中)构造函数、析构函数
  • 海信IP501H-IP502h_GK6323处理器-原机安卓9专用-优盘卡刷固件包
  • ZLMediaKit流媒体服务器WebRTC页面显示:使用docker部署
  • Android多开实现方案深度分析
  • Android13重置锁屏(2)
  • 论文略读:Knowledge is a Region in Weight Space for Finetuned Language Models
  • springboot集成LangChain4j
  • 世博会无法在Android上启动项目:无法连接到TCP端口5554:连接被拒绝