Как мне найти длину строки, используя NASM? - PullRequest
3 голосов
/ 24 июня 2011

Я пытаюсь создать программу с использованием NASM, которая принимает данные из аргументов командной строки. Поскольку длина строки не указана, я пытаюсь создать функцию для вычисления своей собственной. Вот моя попытка, которая берет указатель на строку в регистре ebx и возвращает длину строки в ecx:

len:
    push ebx
    mov ecx,0
    dec ebx
    count:
        inc ecx
        inc ebx
        cmp ebx,0
        jnz count
    dec ecx
    pop ebx
    ret

Мой метод состоит в том, чтобы пройти строку, символ за символом, и проверить, является ли это нулем. Если это не так, я увеличиваю ecx и перехожу к следующему символу. Я считаю, что проблема в том, что cmp ebx,0 неправильно для того, что я пытаюсь сделать. Как мне правильно проверить, является ли персонаж нулевым? Кроме того, есть ли другие вещи, которые я мог бы сделать лучше?

Ответы [ 3 ]

4 голосов
/ 24 июня 2011

Вы сравниваете значение в ebx с 0, которое не то, что вы хотите.Значение в ebx является адресом символа в памяти, поэтому его следует разыменовывать следующим образом:

cmp byte[ebx], 0

Кроме того, последний push ebx должен быть pop ebx.

1 голос
/ 27 октября 2013

Вот как я это делаю в 64-битном исполняемом файле Linux, который проверяет argv[1]. Ядро запускает новый процесс с argc и argv[] в стеке, как описано в x86-64 System V ABI.

_start:
    pop    rsi              ; number of arguments (argc)
    pop    rsi              ; argv[0] the command itself (or program name)
    pop    rsi              ; rsi = argv[1], a pointer to a string
    mov    ecx, 0           ; counter
.repeat:
    lodsb                   ; byte in AL
    test   al,al            ; check if zero
    jz     .done            ; if zero then we're done
    inc    ecx              ; increment counter
    jmp    .repeat          ; repeat until zero
.done:
    ; string is unchanged, ecx contains the length of the string


; unused, we look at command line args instead
section .rodata
    asciiz:    db    "This is a string with 36 characters.", 0

Это медленно и неэффективно, но легко понять.

Для эффективности вы бы хотели

И, конечно, SSE2 всегда доступен в x86-64, поэтому мы должны использовать его для проверки блоков размером 16 байт (после достижения границы выравнивания). Смотрите оптимизированные рукописные strlen реализации, как в glibc. (https://code.woboq.org/userspace/glibc/sysdeps/x86_64/strlen.S.html).

0 голосов
/ 26 июня 2011

Вот как бы я его закодировал

len:
      push ebx
      mov  eax, ebx
lp:
        cmp byte [eax], 0
        jz  lpend
        inc eax
        jmp lp
lpend:
        sub eax, ebx

      pop ebx
      ret

(результат в eax).Скорее всего, есть лучшие способы.

...