【问题标题】:counting the '0's in a string in assembly在汇编中计算字符串中的'0'
【发布时间】:2021-03-03 04:28:43
【问题描述】:

我有一个用 c 和汇编编写的小程序。原理很简单:“计算 main.c 给出的字符串中的‘0’

所以对于test0 str0ing 0,它应该返回3,因为字符串中有3个'0' 函数本身是用 AT&T 语法在 x86 asm 中创建的,我通过 C 获得了一个指向字符串的指针。main.c 和 asm 都通过头文件链接。

到目前为止,这是我的代码,问题是它总是返回 0。它永远不会达到条件跳转以递增 %eax(要返回)

// C

#include "asm.h"

char string[] = "2a0 a0 ";
char *ptr1 = string;

int main(){
    
    printf("\nthere are : %d %s in :%s", zero_count(), "0s", string);
    printf("\nstring address is: %p\n", ptr1);
    
    return 0;
}

// x86asm

    .global ptr1

.section .text
    .global zero_count          #func()
    

zero_count:

    # prologue
    pushl %ebp              # save these previous stack frame pointer
    movl %esp, %ebp         # the stack frame pointer for function
    
    # save registers
    #pushl $ebx             # needs to be pushed out of stack when used
    #pushl %esi             # needs to be pushed out of stack when used
    #pushl %edi             # needs to be pushed out of stack when used
    
    # function body
    movl ptr1, %ecx         # moves the value of ptr1 to ecx
    movl $0, %eax           # cleans eax with 0
                    
    # loop start
    loop_beginning:
        cmp $0, (%ecx)
        je end
        
        # compare to 'o'
        cmp $48, %ecx       # 48 is "0" in the asci table
        je if_0
        
        increment_pointer:
            addl $1, %ecx
            jmp loop_beginning
        
        if_0:
            addl $1, %eax
            jmp increment_pointer
            
    end:
    #popl %edi              # needs to be popped when used
    #popl %esi              # needs to be popped when useds
    #popl %ebx              # needs to be popped when used
    
    # epilogue
    movl %ebp, %esp         # restore the previous stack pointer("cleaner" the stack)
    popl %ebp               # restore the previous stack frame pointer
    ret                     #w returns

我为提前使用全局变量道歉,我知道这不好但我仍在学习使用堆栈

【问题讨论】:

  • cmp $48, %ecx - ECX 持有一个指针,而不是一个字符值。由于您要检查0(终止符)和'0'(ASCII 数字),您应该将movzbl 加载到像EDX 这样的寄存器中。
  • 还要注意cmp $48, (%ecx) 是一个双字,而不是一个字节比较。请改用cmpb $48, (%ecx)
  • @fuz:知道 GAS 是否会像 mov $0, (%ecx) 那样接受 cmp $0, (%ecx) 上的错误补丁作为不明确的操作数大小吗?这似乎并不罕见。顺便说一句,我查看了现有的重复项,但没有运气。不过,我确信有多个问答是比较指针而不是指向的数据,因此只发表评论。
  • @PeterCordes 不确定。也许对.att_syntax 指令有一个新选项? IIRC LLVM 汇编器实际上可能拒绝模棱两可的操作数大小。
  • @fuz 但不是 ecx 将填充 16 位地址吗?我只是比较与()指向的地址是什么

标签: c string assembly x86 att


【解决方案1】:

通过将 cmp 切换为 cmpb 在此字符串中起作用。但我仍然不知道为什么。如果这是一个 int[],这个操作也会起作用吗?

    .global ptr1

.section .text
    .global zero_count          #func()
    

zero_count:

    # prologue
    pushl %ebp              # save these previous stack frame pointer
    movl %esp, %ebp         # the stack frame pointer for function
    
    # save registers
    #pushl $ebx             # needs to be pushed out of stack when used
    #pushl %esi             # needs to be pushed out of stack when used
    #pushl %edi             # needs to be pushed out of stack when used
    
    # function body
    mov ptr1, %ecx          # moves the value of ptr1 to ecx
    movl $0, %eax           # cleans eax with 0
                    
    # loop start
    loop_beginning:
        cmpb $0, (%ecx)
        je end
        
        # compare to 'o'
        cmpb $48, (%ecx)        # 48 is "0" in the asci table
        je if_0
        
        increment_pointer:
            addl $1, %ecx
            jmp loop_beginning
        
        if_0:
            addl $1, %eax
            jmp increment_pointer
            
    # movl (%ecx), %eax
    
    end:
    #popl %edi              # needs to be popped when used
    #popl %esi              # needs to be popped when useds
    #popl %ebx              # needs to be popped when used
    
    # epilogue
    movl %ebp, %esp         # restore the previous stack pointer("cleaner" the stack)
    popl %ebp               # restore the previous stack frame pointer
    ret                     #w returns

【讨论】:

  • 不,当然不会。您必须将数据大小调整为 l 以获得 32 位值,并将 addl $1, %ecx 更改为 addl $4, %ecx 以 4 字节步长遍历数组。
猜你喜欢
  • 2021-03-04
  • 1970-01-01
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多