`
qdujunjie
  • 浏览: 110381 次
  • 性别: Icon_minigender_1
  • 来自: Mars
社区版块
存档分类
最新评论

汇编语言裁剪字符串代码分析(11)?

阅读更多

 

 

 

来自于《Intel汇编语言程序设计》(第四版)第八章。

 

 

裁剪字符串过程从以空字符串结尾的字符串中删除特定字符之后的所有字符。

 

需要的知识:

 

1.

重复前缀。

字符串操作指令本身每次只处理一个内存值。但如果增加一个重复前缀的话,该指令就会使用ECX作为计数器进行重复。

几个重复前缀如下:

 

REP                      当ECX>0时重复

REPZ,REPE           当零标志被设置并且ECX>0时重复

REPNZ,REPNE       当零标志被清除并且ECX>0时重复

 

2.

SCASB,SCASW和SCASD指令,将AL/AX/EAX中的值同目标内存中的字节,字或双字相比较,目标内存数据是由EDI寻址的

这些指令在一个长字符串或数组中查找一个值的时候特别有用。

如果使用REPE(或REP)前缀,当ECX>0并且AL/AX/EAX不能匹配内存中的值时,指令将继续扫描字符串或数组。

REPNE前缀使得指令扫描字符串直到AL/AX/EAX匹配内存中的一个值ECX=0为止。

 

例如下面扫描匹配字符的例子,在字符串变量alpha中查找字符"F",如果找到了该字母,EDI指向匹配字符串后面的一个字符(如果没有找到匹配项,就会执行JNZ指令退出):

 

.data

alpha BYTE "ABCDEFGH",0

.code

mov edi,OFFSET alpha              ; EDI points to the string

mov al,'F'                                  ; search for the letter F

mov ecx,LENGTHOF alpha         ; set the search count

cld                                             ; direction = up

repne scasb                              ; repeat while not equal 

jnz quit                                     ; quit if letter not found

dec edi                                      ; found : back up EDI

 

整个程序的重点就在于红色部分,他会一直循环,直到匹配了F或者ECX=0为止。甚至在循环完之后,还会对是这两种条件的哪一种进行判断。如果是ECX=0(就是循环了所有的字符之后仍未找到),则直接quit;如果不是,则必定是因为匹配了F,则将EDI后退一个字节,指向被匹配的这个字符。

 

 

在Str_trim中,我们也要用到scasb

 

 

3.

字符串指令使用CPU的方向标志来决定ESI和EDI是自动增加还是自动减少:

 

可以使用CLD和STD指令显式地改变,CLD将清除方向标志,STD设置方向标志,其造成影响如下所示:

 

方向标志被清除:ESI和EDI自动增加,寻址顺序按照从低到高。

方向标志被设置:ESI和EDI自动减少,寻址顺序按照从高到低。

 

 

 

 

 

 

下面我们来看一下裁剪字符串程序源代码:

 

;----------------------------------------------------------------------------

Str_trim PROC USES eax ecx edi,

   pString : PTR BYTE,                           ; points to string

   char : BYTE                                        ; char to remove

;

; remove all occurrences of a given character from

; the end of a string.

; Returns : nothing

;----------------------------------------------------------------------------

         mov edi,pString

         INVOKE Str_length,edi        ; returns length in EAX

         cmp eax,0                           ; zero-length string ?

         je L2                                    ; yes : exit

         mov ecx,eax                        ; no : counter = string length

         dec eax

         add edi,eax                         ; EDI points to last char

         mov al , char                        ; char to trim

         std                                       ; direction = reverse

         repe scasb                           ; skip past trim character

         jne L1                                   ; remove first character ?

         dec edi                                 ; adjust EDI : ZF=1 && ECX=0

L1:    mov BYTE PTR [edi+2],0       ; insert null byte

L2:    ret

Str_trim ENDP

        

        

程序首先使用:

 

USES eax ecx edi,

 

将这几个寄存器的值压进堆栈保存起来。

 

然后函数接受两个参数:

 

   pString : PTR BYTE,                           ; points to string

   char : BYTE                                        ; char to remove

 

 

 第一个是指向字符串的地址,第二个是待查找删除的字符。

 

下面是程序体:

 

 

         mov edi,pString                  ; 程序首先将接收到得pString地址保存到edi中

         INVOKE Str_length,edi        ; 调用Str_length过程求的接收到的pString的长度,长度值会被保存到eax中

         cmp eax,0                           ; 长度值是否为0?

         je L2                                    ; 如果为零,则跳转到L2,程序结束。

         mov ecx,eax                        ; 如果不为零,则将字符串长度保存到ecx中

         dec eax                               ; eax中的长度值减1

         add edi,eax                         ; 将edi指向字符串pString的最后一个字符

         mov al , char                        ; 将要查找删除的字符保存到al中

         std                                       ; ESI和EDI将在执行字符串指令时自动减少,并且寻址顺序是由高到低

         repe scasb                           ; 没看懂

         jne L1                                   ; 没看懂

         dec edi                                 ; 没看懂

L1:    mov BYTE PTR [edi+2],0       ; 没看懂

L2:    ret

 

 

后面代码没看懂,始终不明白为什么要将edi指向最后一个字符,后面的那些操作也不清楚。

分享到:
评论

相关推荐

    c语言、ubuntu,脚本基础知识整理

    - **编译阶段**: 编译器会检查代码的规范性和语法错误,然后将代码翻译成汇编语言。可以使用 `-S` 选项让编译器仅执行编译操作并输出汇编代码,例如: `gcc -S hello.i -o hello.s`。 - **汇编阶段**: 汇编器将汇编代码...

    嵌入式前三阶段学习代码例程

    4. **汇编语言**:虽然在高级编程中不常用,但了解汇编能帮助理解底层硬件操作。 5. **I/O接口**:学习如何与外部设备如传感器、LED、串口通信等进行交互。 **进阶阶段** 进阶阶段主要涉及操作系统和驱动程序开发...

    OLED取模教程以及软件

    4. **生成代码**:完成取模后,软件会自动生成对应的C语言或汇编语言代码,这些代码包含了像素数据和必要的显示函数。将这段代码嵌入到你的项目中,就可以在OLED屏幕上显示你之前处理过的字符、数字或图片了。 5. *...

    一步步写嵌入式操作系统

    在汇编语言中,位置计数器(Location Counter)用来跟踪当前指令在存储器中的地址。通过设置位置计数器,可以指定程序的起始地址或者数据段的起始地址。 #### 示例代码 以下是一个简单的示例,展示了如何在ARM架构...

    Python和计算机编程入门

    - **汇编语言**:接近机器语言但更易于阅读和编写。 - **高级语言**:如Python、Java等,接近自然语言,易于理解和编写。 **3. 算法与数据结构** - **算法**:解决特定问题的一系列步骤。 - **数据结构**:组织、...

    嵌入式软件开发学习思路.doc

    - 字符串训练:字符串处理函数的使用。 - C库函数编程接口实践:掌握常用库函数接口的使用。 #### 第四阶段:Linux环境高级编程及项目开发 - **学习目标**:掌握Linux下高级编程技术,具备系统编程能力。 - **...

    嵌入式Linux系统开发技术详解.基于ARM,嵌入式linux系统开发与应用,C,C++源码.zip

    1. **嵌入式Linux系统**:嵌入式Linux是将Linux操作系统裁剪优化后应用于嵌入式设备上的一种系统,它具备开放源代码、可定制性强、稳定性和兼容性好等优点,广泛应用于各种物联网设备、智能家居、汽车电子、工业自动...

    ARM嵌入式系统课后习题部分答案.pdf

    ARM汇编程序所支持的变量有数字变量、逻辑变量、字符变量和字符串变量等。 LPC2000系列ARM7微控制器的UART接收器FIFO触发器可设置为1、4、8或14个字节。LPC2000系列微控制器的定时器主要用于三方面:对内部事件进行...

    嵌入式实习目的和报告.docx

    在Linux环境下强化C编程训练阶段,学生将通过各种编程练习,如整数算法、递归、栈操作、位操作和字符串处理,提高编程能力和调试技巧。第四阶段则进一步深入到Linux高级编程,涉及系统编程(如信号处理、系统调用、...

    嵌入式课件

    9.3.3 基于Windows下ADS的汇编语言程序结构 9.3.4 基于Linux下GCC的汇编语言程序结构 9.4 ARM汇编语言程序调试 9.4.1 ADS软件模拟环境下的程序调试 9.4.2 ADS硬件仿真器环境下的程序调试 9.4.3 ADS Wiggler调试电缆...

    ActionScript开发人员指南中文版

    actionScript 3.0开发人员指南中文版,总共67章,955页。学习actionScript不错的书籍。 目录: 目录 第章:使用日期和时间 管理日历日期和时间 控制时间间隔 ...第章:Adobe图形汇编语言(AGAL) AGAL字节码格式

    uC_OS_在LPC2200平台上的移植

    由于涉及CPU寄存器的操作,这部分代码通常使用汇编语言编写。实现多任务切换主要包括保存和恢复CPU状态等操作。 - **处理器要求**:为了确保μC/OS-II能够顺利运行,LPC2200处理器需要满足几个基本条件,包括支持...

    嵌入式实习报告总结.docx

    3. Linux上的C强化编程训练:强化整数算法、递归和栈编程、位操作、指针、字符串和C库函数的实践,提升在Linux环境下的编程和调试能力。 4. Linux环境高级编程及项目开发:涵盖系统编程、文件I/O、多任务和多线程...

    使用ARM 标准 C 库进行嵌入式应用程序开发

    这些函数覆盖了文件输入输出、数学运算、字符串操作等基础功能,它们通过ARM特有的semihosted环境实现了与目标硬件的交互。semihosting是一种机制,允许在无输入输出硬件的目标设备上运行的应用程序通过与主机通信,...

    嵌入式实习报告总结.pdf

    3. **Linux C强化编程**:进一步强化C语言编程,涵盖整数算法、递归和栈、位操作、指针、字符串训练,以及C库函数接口实践,增强编程理解和调试技能。 4. **Linux高级编程及项目开发**:学习系统编程,如信号处理、...

    Linux移植过程真实体验

    - **ARM汇编**:BOOTLOADER的第一部分通常用汇编语言编写,因为这是启动过程中最早执行的部分,需要对硬件有直接的控制。 - **第一阶段**:此阶段主要负责硬件初始化,包括设置内存映射、时钟配置等,然后将第二...

    嵌入式测验考试前课件PPT所有内容.doc

    - **编译**:将源代码转换为汇编代码。 - **汇编**:将汇编代码转换为机器码。 - **链接**:将多个对象文件链接成可执行文件。 #### 8. Makefile 的概念与作用 - **定义**:一种用于自动化构建过程的脚本文件。 - *...

    ARM嵌入式系统实验教程(二)

    实验可能涉及汇编语言编程,理解指令集架构,以及简单的中断处理。此外,还会介绍如何在开发板上运行第一个“Hello World”程序,以实现对CPU和基本输入输出系统的初步控制。 第三章则进入基于uc/Linux操作系统的...

    ARM基础实验.doc

    介绍了如何使用汇编语言编写简单的程序,包括数据声明、数据处理等基本操作。 - **实验二:汇编指令实验2** 进一步探讨了条件跳转、循环控制等高级汇编语言技巧。 - **实验三:C语言程序实验1** 演示了如何使用...

Global site tag (gtag.js) - Google Analytics