Распределение памяти ассемблера
Я пытался решить эту проблему в течение нескольких дней. Я понятия не имею, как выделить память для копирования строки в другое место. Вот код:
Строка процесса 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
Конечно, вам не нужно использовать его как функцию, вы можете просто поместить код в тело вашей ассемблерной программы, но так как вы часто его используете, это помогает использовать его как функцию.