Распределение памяти ассемблера

Я пытался решить эту проблему в течение нескольких дней. Я понятия не имею, как выделить память для копирования строки в другое место. Вот код:

Строка процесса caesarAsm: DWORD, ключ: DWORD, строкаДлина: DWORD; внутри этой процедуры у меня есть код, который шифрует строковое значение, используя Цезарь шифр 


        Mov Eax, строка
        RET         
caesarAsm endp  

Затем в файле CPP, когда я использую функцию:

цезарь1(слово, 13, стрлен (слово))

Это изменяет значение слова, как было передано по ссылке. Я хочу, чтобы это ничего не делало, пока я не сделаю:

слово = цезарь1(слово, 13, стрлен (слово))

Я пытался решить эту проблему с помощью поиска по всему Интернету, но я не нашел ничего полезного. Я думаю, что решение простое, но я не могу его найти. Я пытался сделать что-то с регистрами ESI и EDI. Я думаю, мне нужно выделить новую память, а затем скопировать строку в это выделенное место. Как это сделать?

1 ответ

Исходя из обсуждения в комментариях, основной подход к копированию строки заключается в объявлении метки в.bss и резервировании количества байтов, необходимого для хранения копии строки. Это использует синтаксис Intel, так как у меня нет MASM. Например, вы можете объявить вашу исходную строку в.data. например:

section .data
    str_str1 db 'string one to copy', 0

section .bss
    str_str2 resb 19

Для получения копии загрузите адрес str_str1 в esi и адрес str_str2 в edi, Загрузите количество символов для копирования cx а затем позвоните rep movsb переместить количество байтов, указанное в cx от esi в edi, например:

section .text
                global _start

        _start:
                xor     ecx, ecx            ; clear ecx
                cld                         ; clear direction flag (read L->R)
                lea     esi, [str_str1]     ; load str1 in esi
                lea     edi, [str_str2]     ; load str2 in edi
                mov     cx, 19              ; move 19 into cx for repeat
        rep     movsb                       ; move 19 bytes from str1 -> str2

        exit:
                xor     edi, edi            ; set zero exit code
                mov     eax, 1              ; set int 0x80 number to 60 (0x3c hex)
                int 0x80                    ; call kernel

Это будет копировать str_str в str_str2, Затем вы можете добавить код для их печати и т. Д. Nasm предлагает простой макроязык, чтобы помочь с повторяющимися задачами, такими как вызовы чтения и записи (особенно для отступов, пробелов, печати и т. Д.). Полный пример синтаксиса nasm:

; Following macros simply print indents, newlines and strings to stdout
%macro  indent  1
        mov     eax, 4
        mov     ebx, 1
        mov     ecx, tab
        mov     edx, %1
        int 0x80
%endmacro

%macro  newlns  1
        mov     eax, 4
        mov     ebx, 1
        mov     ecx, onln
        mov     edx, %1
        int 0x80
%endmacro

; strn (string const) macro is overloaded to take 1 or 2 args
%macro  strn    1
        mov     eax, 4
        mov     ebx, 1
        mov     ecx, %1
        mov     edx, 1
        int 0x80
%endmacro

%macro  strn    2
        mov     eax, 4
        mov     ebx, 1
        mov     ecx, %1
        mov     edx, %2
        int 0x80
%endmacro

section .data

    nwln db 0xa
    dnln db 0xa,0xa
    onln times 8 db 0xa     ; 8 newlines
    tab times 8 db 0x20     ; 8 spaces
    msg_str1 db 0xa, '  string_1: '
    msg_str2 db 0xa, '  string_2: '

    str_str1 db 'string one to copy', 0

section .bss

    str_str2 resb 19

section .text
                global _start

        _start:
                xor     ecx, ecx            ; clear ecx
                cld                         ; clear direction flag (read L->R)
                lea     esi, [str_str1]     ; load str1 in esi
                lea     edi, [str_str2]     ; load str2 in edi
                mov     cx, 19              ; move 19 into cx for repeat
        rep     movsb                       ; move 19 bytes from str1 -> str2

                ; macros to print results & add newlines
                strn    msg_str1, 13        ; print str1 msg
                strn    str_str1, 19        ; print str1
                strn    msg_str2, 13        ; print str2 msg
                strn    str_str2, 19        ; print str2
                newlns  2                   ; print 2 newlines

        exit:
                xor     edi, edi            ; set zero exit code
                mov     eax, 1              ; set int 0x80
                int 0x80                    ; call kernel

Nasm compile / link

nasm -f elf -o obj/str_cpy_32.o str_cpy_32.asm
ld -m elf_i386 -o bin/str_cpy_32 obj/str_cpy_32.o

Выход

$ ./bin/str_cpy_32

  string_1: string one to copy
  string_2: string one to copy

Посмотрите на различия синтаксиса MASM и внесите необходимые изменения. Не должно быть никаких причин, по которым вы не сможете выполнить то же самое.

Определение размера строки - 32-разрядный

Как уже говорилось, для определения длины неизвестной строки сама строка должна заканчиваться нулем, чтобы обеспечить конечный символ стража для проверки. Адрес строки находится в edi и затем вы эффективно проверяете каждый символ на ноль (числовой ноль, а не нулевой символ), а длина определяется числом итераций, необходимых для достижения символа, заканчивающегося нулем:

; szstr computes the length of a string.
; edi - string address
; edx - contains string length (returned)
section .text
    strsz:
            xor     ecx, ecx    ; zero rcx
            not     ecx         ; set rcx = -1 (uses bitwise id: ~x = -x-1)
            xor     al,al       ; zero the al register (initialize to NUL)
            cld                 ; clear the direction flag
            repnz   scasb       ; get the string length (dec ecx through NUL)
            not     ecx         ; rev all bits of negative -> absolute value
            dec     ecx         ; -1 to skip the null-term, ecx contains length
            mov     edx, ecx    ; size returned in edx, ready to call write
            ret

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

Другие вопросы по тегам