【问题标题】:How to compare a symbol with string in Gasm (Gnu Assembler)?如何在Gasm(Gnu Assembler)中将符号与字符串进行比较?
【发布时间】:2013-05-25 14:47:53
【问题描述】:

我需要使用 gasm 计算字符串中的空格数。所以,我用简单的程序写了,但是比较不起作用。

.section .data
  str:
    .string " TEst   string wit h spaces   \n"

.section .text
.globl _start
_start:

movl $0,%eax # %eax - amount of spaces
movl $0,%ecx # Starting our counter with zero

loop_start:
  cmpl $32,str(,%ecx,1)  # Comparison (this is never true)
  jne sp
  incl %eax # Programm never goes there
  incl %ecx
  jmp loop_start
sp:
  cmpl $0X0A,str(,%ecx,1) #Comparison for the end of string
  je loop_end #Leaving loop if it is the end of string
  incl %ecx
  jmp loop_start
loop_end:
  movl (%eax),%ecx  # Writing amount of spaces to %ecx
  movl $4,%eax
  movl $1,%ebx
  movl $2,%edx
  int $0x80

  movl $1,%eax
  movl $0,%ebx
  int $0x80

所以,这个字符串cmpl $32,str(,%ecx,1) 的问题在那里我尝试将空间(ASCII 中的 32)与 str 的 1 个字节(我使用 %ecx 作为位移计数器,并占用 1 个字节)进行比较。不幸的是,我在 Internet 上没有找到任何关于 Gasm 中符号比较的示例。我尝试使用 gcc 生成的代码,但我无法理解和使用它。

【问题讨论】:

    标签: linux assembly gnu


    【解决方案1】:

    这永远不会返回 true,我想我知道为什么:

    cmpl $32,str(,%ecx,1)
    

    因为您将立即数与内存地址进行比较,所以汇编器无法知道两个操作数的大小。因此,可能假设每个参数都是 32 位,但您想比较两个 8 位值。您需要某种方式来明确声明您正在比较字节。我的解决方案是:

    mov str(,%ecx,1), %dl  # move the byte at (str+offset) into 'dl'
    cmp $32, %dl           # compare the byte 32 with the byte 'dl'.
    # hooray, now we're comparing the two bytes!
    

    可能有更好的方法来显式比较字节,我可能在某个地方犯了一个愚蠢的错误;我对 AT&T 语法不太熟悉。但是,您应该了解您的问题是什么,以及如何解决它。

    【讨论】:

    • 谢谢,它有效。现在我知道 gcc 也在做同样的事情,但是很难理解,因为它将代码 for (i=0;i<20;i++) { if (str[i]==' ') a++; } 翻译成 .L4: movl -8(%rbp), %eax cltq movzbl -112(%rbp,%rax), %eax cmpb $32, %al jne .L3 addl $1, -4(%rbp) .L3: addl $1, -8(%rbp)
    • @rulevoi 很高兴我能帮上忙 :)
    • GAS 不需要做任何假设; cmpl 是明确的 32 位操作数大小。这就是l 后缀在 AT&T 语法中的含义。 cmpb $' ', str(%ecx) 将是一个字节比较。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-02
    • 1970-01-01
    • 1970-01-01
    • 2022-08-14
    • 1970-01-01
    • 2016-01-24
    相关资源
    最近更新 更多