#assembly #x86 #nasm
#сборка #x86 #nasm
Вопрос:
Я хочу изменить значение переменной в NASM.
Я долго искал в интернете и много чего перепробовал.
Я уже пробовал это:
global _main
extern _printf
section .data
original: db "Hello, world", 10, 0
new: db "Hello", 10, 0
section .text
_main:
mov [original], new
push original
call _printf
add esp, 4
ret
Это не работает, поэтому я попробовал это сделать.
global _main
extern _printf
section .data
original: db "Hello, world", 10, 0
new: db "Hello", 10, 0
section .text
_main:
mov eax, new
mov [original], eax
push original
call _printf
add esp, 4
ret
Ну, он работает без ошибок, но продолжает печатать странные вещи.
@@
(На самом деле, в начале строки выше были символы в форме стрелок, указывающие вверх и вниз, но я опустил их, потому что они, похоже, не были распознаны)
Я пробовал и искал много вещей. Но я не мог найти решения. Итак, как я могу изменить значение переменной в NASM? (Я использую сборку x86 в Windows)
Спасибо.
Комментарии:
1. Это 32- или 64-битный код? Как вы собираете и связываете этот код?
2.@fuz Это то, как я скомпилировал
nasm -f win32 print.asm
gcc print.obj -o print.exe
3. Вы печатаете значение указателя в виде байтов ASCII, а не в указанной памяти. Просто передайте указатель на
new
или измените aptr: dd original
, а затем перезагрузите его.4. вы пытаетесь изменить строку (скопировать ее сверху) или пытаетесь указать на новую строку (нажать new вместо push original)?
5. @old_timer Я собираюсь изменить значение original на значение new и нажать original. Итак, я хочу, чтобы было напечатано «Привет».
Ответ №1:
Вы не можете перезаписать строку с помощью одной инструкции. Вам нужно использовать цикл для копирования байтов строки, одновременно проверяя наличие нулевого байта, который отмечает конец строки. Например:
mov edi, original
mov esi, new
.loop:
mov al, [esi]
mov [edi], al
add esi, 1
add edi, 1
test al, al
jnz .loop
Комментарии:
1. Этот код предназначен для общей копии строки. В вашем примере, поскольку вы знаете длину старой и новой строк, вы можете сделать это с помощью нескольких инструкций:
mov eax, [new] / mov [original], eax / mov eax, [new 4] / mov [original 4], eax
. Это копирует на один байт больше, чем фактическая длина строки, что обычно безопасно, но должно выполняться только в том случае, если вы знаете , что это безопасно.2. Регистры edi и esi должны быть сохранены вашей функцией, поэтому вы должны поместить их в начале функции и вставить в конце перед возвратом. В качестве альтернативы используйте
ecx
иedx
в качестве указателей, которые не нужно сохранять.3. Чтобы сделать 7-байтовую копию, вы могли бы использовать стратегию glibc memcpy / memmove из двух перекрывающихся 4-байтовых загрузок и двух хранилищ. Не имеет значения, что средний байт записывается дважды.