Уберите пробелы из строки - PullRequest
2 голосов
/ 18 ноября 2011

Я пытаюсь изучить ассемблер (Intel x86 с NASM на Linux), и неудивительно, что у меня возникли некоторые проблемы.

Следующее предназначено для того, чтобы взять буфер текста, удалить все пробелы и поместить результат в другой буфер. Это часть более крупного проекта, который я делаю как способ обучения, и сначала я разрабатываю каждую часть отдельно. В реальном проекте сообщение будет приходить из файла, здесь я просто использую жестко закодированную строку (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

Мне интересно, почему мне нужно использовать dword в строке перед call stripwhite выше, когда оба Msg и два буфера используют байты, но компоновщик (в данном случае вызываемый 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

1 Ответ

0 голосов
/ 18 ноября 2011
[SECTION .bss]
BUFFSIZE   equ 80 
BufferA    resb BUFFSIZE
BufferB    resb BUFFSIZE

BufferA - это массив.

mov dword [BufferA], Msg

В этом случае адрес Msg помещается в первые 4 байта BufferA, вероятно, не то, что вам нужно.Вы можете позвонить memcpy вместо.

...