如何在汇编中通过字符串进行索引

2024-02-29

给定变量:

var1    db  "abcdefg", NULL

我将如何执行循环来导航每个字母?在 C++ 中,您可以在循环内执行类似 var[x] 的操作,然后每次递增 x。有任何想法吗?


在 C 和 C++ 中,字符串以 NUL 结尾。这意味着将 ASCII NUL 字符 (0) 添加到字符串的末尾,以便代码可以判断字符串的结尾位置。这strlen函数从头开始遍历字符串,并不断循环,直到遇到该 NUL 字符。当它找到 NUL 时,它知道这是字符串的结尾,并且它返回从开头到 NUL 的字符数作为字符串的长度。

字符串文字(双引号中的内容)由 C/C++ 编译器自动以 NUL 结尾,因此:

"abcdefg"

等价于下面的数组:

{'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}

我提到这一点是因为 Peter Rader 在他的回答中提出了这一点,而你并没有真正理解他在说什么。但是,您似乎已经知道这一点,因为您在程序集声明中的字符串中附加了一个 NUL 字符:

var1    db  "abcdefg", NULL

现在,一般来说,我们不使用标识符NULL为了这。尤其是在 C 语言中,NULL被定义为空指针。我们只使用文字 0,因此定义为:

var1    db  "abcdefg", 0

但你的代码可能有效,假设NULL某处定义为 0。

所以你的设置全部正确。现在您需要做的就是编写循环:

    mov  edx, OFFSET var1    ; get starting address of string

Loop:
    mov  al, BYTE PTR [edx]  ; get next character
    inc  edx                 ; increment pointer
    test al, al              ; test value in AL and set flags
    jz   Finished            ; AL == 0, so exit the loop

    ; Otherwise, AL != 0, so we fell through.
    ; Here, you can do do something with the character in AL.
    ; ...

    jmp  Loop                ; keep looping

Finished:

你说你熟悉CMP操作说明。在上面的代码中,我使用了TEST而不是CMP。你可以等效地写:

cmp  al, 0

but

test al, al

效率稍高一些,因为它是一条较小的指令,所以我只是习惯在将寄存器的值与 0 进行比较的特殊情况下这样编写。编译器也会生成此代码,所以它很好熟悉它。


奖金闲聊:表示字符串的另一种方法是将其长度(以字符为单位)与字符串本身一起存储。这就是 Pascal 语言传统上所做的事情。这样,您就不需要在字符串末尾使用特殊的 NUL 标记字符。相反,该声明将如下所示:

var1    db  7, "abcdefg"

其中每个字符串的第一个字节是它的长度。与 C 风格相比,这具有多种优点 https://www.joelonsoftware.com/2001/12/11/back-to-basics/,即您不必迭代整个字符串来确定其长度。当然,主要缺点是字符串的长度限制为 255 个字符,因为这就是一个 BYTE 所能容纳的全部字符。

无论如何,在预先知道长度的情况下,您不再检查 NUL 字符,您只需迭代与字符串中的字符相同的次数:

    mov  edx, OFFSET var1    ; get starting address of string
    mov  cl, BYTE PTR [edx]  ; get length of string

Loop:
    inc  edx                 ; increment pointer
    dec  cl                  ; decrement length
    mov  al, BYTE PTR [edx]  ; get next character
    jz   Finished            ; CL == 0, so exit the loop

    ; Do something with the character in AL.
    ; ...

    jmp  Loop                ; keep looping

Finished:

(在上面的代码中,我假设所有字符串都是minimum长度为 1 个字符。这可能是一个安全的假设,并且避免了在循环上方进行长度检查的需要。)

或者,您可以执行您提到的数组索引,但如果您想迭代,则必须小心一点forwards通过字符串:

    mov   edx, OFFSET var1        ; get starting address of string
    movzx ecx, BYTE PTR [edx]     ; get length of string
    lea   edx, [ecx+1]            ; increment pointer by 1 + number of chars
    neg   ecx                     ; negate the length counter
Loop:
    mov   al, BYTE PTR [edx+ecx]  ; get next character

    ; Do something with the character in AL.
    ; ...

    inc   ecx
    jnz   Loop                     ; CL != 0, so keep looping

基本上,我们设置EDX指向end的字符串,我们设置计数器(ECX)到negative字符串的长度,然后我们通过索引读取字符[EDX+ECX](因为我们否定了ECX,相当于[EDX-ECX]).

几乎可以肯定,有一种比我在这里想到的更好(更聪明)的方法来做到这一点,但你应该明白这个想法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在汇编中通过字符串进行索引 的相关文章

  • Haswell 及其后续产品上的 A20 系列是否仍会被屏蔽?

    维基百科引用了英特尔手册中的这一说法 A20M 的功能主要由较旧的操作系统使用 现代操作系统不使用 在较新的 Intel 64 处理器上 A20M 可能不存在 现在的手册中实际上有这样一个短语 但它是含糊不清的 Does A20M 实际上仅
  • Java中char数组的默认值是多少?

    如果我像这样分配字符数组 char buffer new char 26 它分配的默认值是什么 我尝试打印它 但它只是一个空字符 System out println this is what is inside gt buffer 1 t
  • 在字符串中间添加一个字符

    可能有一个简单的解决方案可以解决这个问题 但会引起面部表情 我将时间存储为 4 个字符长的字符串 即 1300 我试图将该字符串显示为 13 00 我觉得必须有一个比我现在正在做的更优雅的解决方案 我目前有 startTime get fi
  • 无法在“System.String”类型上的多个长度相等的构造函数之间进行选择

    尝试解析类型时出现以下错误 无法在 System String 类型上的多个长度相等的构造函数之间进行选择 注册组件时 使用UsingConstructor 配置方法显式选择构造函数 该类型有 1 个构造函数 该构造函数采用IReposit
  • gcc 没有小字符串优化吗?

    Most std string实现 包括 GCC 使用小字符串优化 例如 有一个answer https stackoverflow com a 21710033 2640636讨论这个 今天 我决定检查我编译的代码中的字符串在什么时候被移
  • java中如何连接字符串

    这是我的字符串连接代码 StringSecret java public class StringSecret public static void main String args String s new String abc s co
  • Python:字符串不会转换为浮点数[重复]

    这个问题在这里已经有答案了 我几个小时前写了这个程序 while True print What would you like me to double line raw input gt if line done break else f
  • shell中如何分割字符串

    我有一个变量作为 string ABC400p2q4 我怎样才能分开ABC400 and p2q4 我需要将它分成两个变量 结果我得到 echo var1 ABC400 echo var2 p2q4 可以用任何字母字符代替 ABC 可以用任
  • 如何修复:“无法解析类型 java.lang.CharSequence。它是从所需的 .class 文件间接引用的”消息? [复制]

    这个问题在这里已经有答案了 我正在尝试使用这个字符串 amountStr amountStr replace replace replace 但我收到一条错误消息 我知道我收到的错误消息是因为我刚刚发布的字符串已过时 所以我想知道该字符串的
  • 确定数组的大小(如果传递给函数)

    如果将数组传递给另一个函数 未传递大小 是否可以确定数组的大小 数组的初始化类似于 int array XXX 我知道不可能执行 sizeof 因为它会返回指针的大小 我问的原因是因为我需要在传递数组的另一个函数内运行 for 循环 我尝试
  • 从 64 位 nasm 代码接收 32 位寄存器

    我正在学习 64 位 nasm 我通过执行以下操作来汇编 nasm 文件 该文件仅包含 64 位寄存器 nasm f elf64 HelloWorld nasm o HelloWorld o 并链接它执行以下操作 ld HelloWorld
  • 如何使用 CNContacts 快速获取手机号码?

    我有一些代码可以检索用户联系人中的所有电话号码 但只想过滤掉手机号码 目前 我只是通过将第一个数字为 或第二个数字为 7 的数字添加到数组中来实现此目的 如下所示 func findContacts gt CNContact let key
  • Python str.format() 方法的默认 kwarg 值

    我希望尝试使现有字符串的复数化尽可能简单 并且想知道是否有可能得到str format 在查找 kwargs 时解释默认值 这是一个例子 string number of sheep sheep has run away dict comp
  • 制作一个js数组,输入框的值用空格分隔

    我正在尝试使用文本框进行用户输入并将它们放入数组中 基本上 如果用户输入像这样的字符串 10 23 4566 234 10 我希望将数字放入 10 23 4566 234 10 等数组中 这可能吗 我只处理数字 字符串可能会很长 你会想要使
  • 当从字符串文字初始化 char 数组时会发生什么?

    据我了解 以下代码的工作原理如下 char cptr Hello World Hello World 住在 rodata程序内存的一部分 字符串文字 Hello World 返回一个指向字符串基地址的指针 或者所谓 数组 中第一个元素的地址
  • 如何消除字符串中的所有换行符?

    我需要删除字符串中出现的所有换行符 来自数据库 我使用下面的代码来做到这一点 value Replace r n Replace n Replace r 我可以看到至少有一个角色的行为就像行尾一样幸存了下来 字符代码是8232 http w
  • 以编程方式将字符串宽度值插入到 sprintf() 中

    我正在尝试以编程方式将字符串宽度值插入到sprintf 格式 期望的结果是 sprintf 20s hello 1 hello 但我想插入20在同一通话中即时进行 因此它可以是任何号码 我努力了 sprintf ds 20 hello 1
  • 从字符串末尾删除多个字符类型

    我有一个构建地址字段的循环 其中一些字段在字符串末尾可能为空 List
  • 确定 C 字符串是否是 C 中的有效 int

    我需要检查 C 字符串是否是有效整数 我都尝试过 int num atoi str and int res sscanf str d num 但发送字符串 8 9 10 这两行都仅返回 8 而没有指示该字符串的无效性 谁能提出替代方案 看看
  • 在 String.Format 中插入格式化字符?

    我用谷歌搜索了这个 但 VB Net 2008 似乎不允许在 String Format 中插入格式化字符 例如 t r n BAD MessageBox Show String Format 0 tab 1 Foo Bar BAD Mes

随机推荐

  • linux gcc 链接器与 C 程序的问题

    我正在尝试编译一个包含 c 文件标头的 C 程序 但只有 1 个 c 文件真正使用了头文件中定义的变量 这是一些会产生链接器问题的示例代码 我试图让我的头文件包含 2 使用的全局变量 不同的 c 文件 任何类型的帮助将不胜感激 谢谢 tmp
  • directX 创建交换链

    在我的书中 我编写了创建交换链的代码 IDXGIDevice dxgiDevice 0 mD3dDevice gt QueryInterface uuidof IDXGIDevice void dxgiDevice IDXGIAdapter
  • modelBuilder.IncludeMetadataInDatabase 在 EF CTP5 中的位置在哪里?

    使用 CTP4 我曾经能够执行以下操作 如由 ptrandem 建议 https stackoverflow com questions 3600672 entity framework ctp4 code first how to tur
  • Google Cloud Run 屏蔽授权标头中的承载令牌

    Cloud Run 的 Google 文档指出 您可以 从授权标头中提取令牌 文档在这里 https cloud google com run docs authenticating end users getting user profi
  • 字符串数组中的随机元素[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我有一个字符串数组 String f
  • Heroku 上的 .Net Core 和 Docker

    Context 我正在尝试部署一个ASPNET核心示例应用程序上Heroku https heroku com 与 docker 但不工作 repo https github com mykeels sample web api https
  • 无法通过在 Apache Beam 中创建模板来按所需顺序运行多个管道

    我有两个独立的管道 分别为 P1 和 P2 根据我的要求 我只需要在 P1 完全完成执行后才运行 P2 我需要通过一个模板完成整个操作 基本上 模板在找到 run 方式 即 p1 run 时就被创建 所以我可以看到 我需要使用两个不同的模板
  • 为什么信号处理程序中的 waitpid 需要循环?

    我在一本电子书中读到 waitpid 1 status WNOHANG 应该放在 while 循环下 这样如果多个子进程同时退出 它们都会被收获 我尝试了这个概念 同时创建和终止 2 个子进程 并通过 waitpid 不使用循环来获取它 并
  • 每个日期的 SQL 总金额

    我有一个名为 rentals 的表 其中存储如下数据 id rent id start date end date amount 1 54 12 10 2019 26 10 2019 100 2 54 13 10 2019 20 10 20
  • 检查一个列表是否是 pandas Dataframe 中另一个列表的子集

    所以 我有这个包含近 3000 行的 Dataframe 看起来像这样 CITIES 0 A B 1 A B C D 2 A B C 4 X 5 X Y Z 2670 Y Z 我想从 DF 中删除 CITIES 列表包含在另一行中的所有行
  • 如何在 phantomJS 中执行 jQuery Promise?

    我正在尝试在服务器端使用 nodejs 和 phantomjs 来对我们的网站进行 SEO 虽然 ajax 工作正常 但我无法执行我在代码中使用的自定义承诺 我如何让 phantomJS 等到承诺得到解决 下面是我编码的内容 body ad
  • 将 Android 项目档案导入 Eclipse 时出现问题

    如果这是一个愚蠢的新手问题 我很抱歉 我正在使用 Eclipse Helios 版本 并按照developer android com 的建议配置了 Android SDK 我可以毫无问题地创建和运行新项目 但无法使用 导入 gt 将现有项
  • opencv:将标量转换为浮点或双精度类型

    谁能帮我将 openCV 的标量类型转换为 float 或 double 等基本类型 Scalar Sum1 sum arg1 Sum2 sum arg2 theta at
  • 包装单张 - 地图未显示

    我对 Rstudio 中使用的 传单 包有一些疑问 我的问题是 底图没有显示 但在查看器的底部写着 OpenStreeMap 并且还显示了放大和缩小的选项 有人知道这个问题吗 library leaflet m lt leaflet m l
  • 自定义验证器不显示错误消息

    我有一个要求 需要多个字段之一 使用自定义验证器 偶数会触发 返回 false 但不会显示错误消息并且表单会验证 我缺少什么 我尝试过使用和不使用 ValidationSummary Thanks
  • 更新 JList

    我现在制作了一个基于数组列表的 JList 并由 defaultlistmodel 填充 该列表会在连接到服务器时添加人员 但不会显示连接的人员或之后连接的人员 所以 我必须更新 JList 我的问题是 我应该更新什么 是否可以使用运行更新
  • 带标签的维基数据 SPARQL 查询不起作用

    我不明白为什么通过这个查询我无法获得运动和流派标签 SELECT DISTINCT item itemLabel value inception creatorLabel image group concat genreLabel sepa
  • 如何动态导入 python 模块函数?

    假设my function 位于 my apps views 我想导入my function动态地不使用类似的东西exec or eval 有什么办法可以实现这一点吗 我想做类似的事情 my function import func my
  • 如何在msbuild文件中给出相对路径?

    我正在编写一个 msbuild 文件来使用 galio 运行测试 现在 我需要给出
  • 如何在汇编中通过字符串进行索引

    给定变量 var1 db abcdefg NULL 我将如何执行循环来导航每个字母 在 C 中 您可以在循环内执行类似 var x 的操作 然后每次递增 x 有任何想法吗 在 C 和 C 中 字符串以 NUL 结尾 这意味着将 ASCII