【问题标题】:Strip whitespace from string从字符串中去除空格
【发布时间】:2011-11-18 19:29:45
【问题描述】:

我正在尝试学习汇编(Linux 上带有 NASM 的 Intel x86),不出所料,我遇到了一些麻烦。

以下内容旨在获取文本缓冲区,删除所有空格并将结果放入另一个缓冲区。这是我正在做的一个更大项目的一部分,作为一种学习方式,我首先单独开发每个部分。在实际项目中,消息将来自文件,这里我只是使用硬编码字符串 (Msg) 进行测试。

但它不起作用。我一直在摆弄它一段时间,但我确定我在某处或某处错过了一些基本概念。

[SECTION .data]
Msg   db '    %d Whitespace, thanks      ', 10, 0

[SECTION .bss]
BUFFSIZE   equ 80 
BufferA    resb BUFFSIZE
BufferB    resb BUFFSIZE

[SECTION .text]
extern printf

global main

; PROCEDURE stripwhite
; INPUT     None
; OUTPUT    None
; NOTES     Strips all leading and trailing whitespace from BufferA
;           Result is stored in BufferB
stripwhite:
    pushad                  ; Save caller's registers

    mov eax, BufferA        ; Source string
    mov ebx, BufferB        ; Output string
    .loop:
        mov cl, byte [eax]  ; Get a single character from the source
        cmp cl, 0
        je .end             ; End if character is null
        cmp cl, 32
        jne .save           ; Save it if it's not a space
        add eax, 1          ; Otherwhise skip to next character
        jmp .loop
    .save:
        mov byte [ebx], cl  ; Save character in output buffer
        add eax, 1          ; Move on to next character
        add ebx, 1
        jmp .loop
    .end:
        mov byte [ebx], 0   ; Add a null at the end

    popad                   ; Restore caller's registers
    ret

main:
    push ebp                ; Set up stack frame for debugger
    mov ebp, esp
    push ebx                ; Must preserve ebp, ebx, esi and edi
    push esi
    push edi
    ; start

    mov dword [BufferA], Msg
    call stripwhite

    push 0
    push BufferB            ; Push message string
    call printf             ; Print line count
    add esp, 8              ; Clean up the stack

    ; end
    pop edi                 ; Restore saved registers
    pop esi
    pop ebx
    mov esp, ebp            ; Destroy stack frame
    pop ebp
    ret

我有点想知道为什么当Msg 和两个缓冲区都使用字节时,我似乎必须在上面的call stripwhite 之前的行中使用dword,但是链接器(在这种情况下由 GCC 调用)抛出当我使用其他任何东西时出现错误:

stripwhite.o:stripwhite.asm:82: relocation truncated to fit: R_386_8 against `.data'
collect2: ld returned 1 exit status

也许这与它有关,但我不知道是什么。

以下似乎工作得很好,除了代码不在过程中之外,基本上是相同的。

[SECTION .data]
Msg   db '    %d Whitespace, thanks      ', 10, 0

[SECTION .bss]
BUFFSIZE   equ 80 
BufferA    resb BUFFSIZE
BufferB    resb BUFFSIZE

[SECTION .text]
extern printf

global main

main:
    push ebp                ; Set up stack frame for debugger
    mov ebp, esp
    push ebx                ; Must preserve ebp, ebx, esi and edi
    push esi
    push edi
    ; start

    mov eax, Msg
    mov ebx, BufferB
    .loop:
        mov cl, byte [eax]
        cmp cl, 0
        je .end
        cmp cl, 32
        jne .save
        add eax, 1
        jmp .loop
    .save:
        mov byte [ebx], cl
        add eax, 1
        add ebx, 1
        jmp .loop
    .end:
        mov byte [ebx], 0

    push 0
    push BufferB            ; Push message string
    call printf             ; Print line count
    add esp, 8              ; Clean up the stack

    ; end
    pop edi                 ; Restore saved registers
    pop esi
    pop ebx
    mov esp, ebp            ; Destroy stack frame
    pop ebp
    ret

【问题讨论】:

    标签: linux assembly x86 nasm


    【解决方案1】:
    [SECTION .bss]
    BUFFSIZE   equ 80 
    BufferA    resb BUFFSIZE
    BufferB    resb BUFFSIZE
    

    BufferA 是一个数组。

    mov dword [BufferA], Msg
    

    这是把Msg的地址放在BufferA的前4个字节,可能不是你想要的。你可以打电话给memcpy

    【讨论】:

    • 啊!我知道那条线有些可疑:) 谢谢,这似乎可以解决问题。我假设在汇编中没有比通过 C 库更简单的方法吗?
    • @MCXXIII:你可以做一个rep movs,或者写你自己的循环。
    • 谢谢。编写自己的循环听起来不那么简单,但我可能会研究rep movs
    猜你喜欢
    • 2012-09-01
    • 2012-04-05
    • 2010-12-07
    • 2017-09-20
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    相关资源
    最近更新 更多