Функция Assembly (Intel x86) для определения длины строки, почему я получаю дополнительные символы? - PullRequest
1 голос
/ 01 октября 2019

Я новичок в сборке, и у меня есть домашнее задание, где я должен создать функцию strlen, чтобы найти длину любой строки.

Я попытался вычесть 4 из edx, потому что вижу4 лишних символа в конце, но это ничего не исправило. Они все еще там.

section .data   
text: db "Hello world, trying to find length of string using function."     ;our string to be outputted

section .text
global _start   ;declared for linker

_start:     
    mov eax, 4      ;system call number (sys write)
    mov ebx, 1      ;file descriptor to write-only
    mov ecx, text   ;message to output
    call strlen
    mov edx, len    ;length of string to print
    int 80h         ;interrupt

exit:       
    mov eax, 1  ;system call number (sys exit)
    mov ebx, 0  ;file descriptor to read-only
    int 80h     ;interrupt

strlen: 
    push ebp        ;prologue, save base pointer
    mov ebp, esp    ;copy esp to ebp
    push edi        ;push edi for use

                    ;body
    mov edi, text   ;save text to edi, and i think when i do that edi expands? if text = 5 bytes, and edi was originally 4, then edi becomes 5?
    sub edi, esp    ;subtract edi starting point by the esp starting point to get len. ex: edi = 100, esp = 95
    mov [len], edi  ;copy value of edi onto len

    pop edi         ;epilogue, pop edi out of stack
    mov esp, ebp    ;return esp back to top of stack
    pop ebp         ;pop ebp back to original
    ret             ;return address



section .bss    
len: resb 4 ;4 byte to integer

Допустим, у меня есть следующий код в разделе .data:

section .data   
text: db "Hello world, trying to find length of string using function."

Ожидаемый результат должен быть "Привет мир, попыткачтобы найти длину строки с помощью функции. ", однако я получаю " Hello world, пытаюсь найти длину строки с помощью функции. #### " где # - любой произвольный символ.

Это вывод терминала:

Спасибо.

1 Ответ

1 голос
/ 01 октября 2019

До вызова strlen вы загрузили ECX адрес строки, для которой вы хотите узнать длину. Затем используйте ECX в своей функции напрямую.
Вам не нужно использовать код пролога / эпилога в этой маленькой задаче.

strlen: push    ecx
        dec     ecx
.loop:  inc     ecx
        cmp     byte ptr [ecx], 0
        jne     .loop
        sub     ecx, [esp]
        mov     [len], ecx         ; Save length
        pop     ecx
        ret

Этот код проходит через строку, пока не найдет ноль,В этот момент начальный адрес (он находится в стеке на [esp]) вычитается из адреса, где был найден ноль (он находится в ECX). Это дает длину.

Вместо помещения результата в переменную памяти, вы можете выбрать возвращение его в регистр EDX - готово к использованию в следующем!

Эта версия strlen может работать, только если вы уверены, что строка на самом деле заканчивается нулем. Просто добавьте ноль.

section .data   
text: db "Hello world, trying to find length of string using function.",0

Это NASM

call strlen
mov edx, len    ;length of string to print
int 80h         ;interrupt

Вам нужны квадратные скобки вокруг len , чтобы получитьдлина, которая хранится в этом месте.

call    strlen
mov     edx, [len]    ; Length of string to print
int     80h
...