Как сохранить строковую временную переменную в сборке x86-64 - PullRequest
3 голосов
/ 17 февраля 2020

Я новичок в сборке, и мне нужно написать функцию memmove в сборке x86-64, и она говорит:

Функция memmove () копирует n байтов из области памяти sr c в область памяти dest. Области памяти могут перекрываться: копирование происходит так, как будто байты в sr c сначала копируются в временный массив , который не перекрывает sr c или dest, а затем байты копируются из временный массив в dest.

Тем не менее, я не нахожу способ сохранить временную строку в сборке, и поэтому я публикую это.

Я пытался вставить rax регистр, но у меня ошибка сегментации:

mov r8b, byte [rsi + rcx] ; rsi is source string
mov byte [rax + rcx], r8b

Кстати, я использую nasm -f elf64 memmove.asm в моей сборке

Спасибо.

1 Ответ

1 голос
/ 18 февраля 2020

Машинная инструкция MOVSB ​​ станет вашим другом в копировании областей памяти. Он копирует один байт из памяти, адресованной RSI, в память, адресуемую RDI, а затем изменяет оба регистра на следующий элемент (байт).

SECTION .data 
Memory   DB '0123456789'
Src1st   EQU Memory+0
SrcLast  EQU Memory+4
Dest1st  EQU Memory+3
DestLast EQU Memory+7
SECTION .text
   LEA RSI,[Src1st]
   LEA RDI,[Dest1st]
   CLD

Мы можем визуализировать структуру памяти перед MOVSB ​​таким образом

  RSI   RDI
   |     |
   0 1 2 3 4 5 6 7 8 9 
   _________        Src  
         _________  Dest  

После MOVSB ​​

    RSI   RDI
     |     |
   0 1 2 0 4 5 6 7 8 9 

С префиксом инструкции REP повторяется RCX раз. После

MOV RCX,DestLast-Dest1st+1 
REP MOVSB
                RSI   RDI
                 |     |
       0 1 2 0 1 2 0 1 8 9

Это не работает, как ожидалось, когда области Sr c и Dest перекрываются - вместо 0120123489 у нас есть 0120120189 . Когда поле назначения находится выше источника (RDI> RSI), мы должны скопировать назад (установить флаг направления) и начать с регистров, указывающих на конец полей.

   LEA RSI,[SrcLast]
   LEA RDI,[DestLast]
   MOV RCX,DestLast-Dest1st+1

          RSI   RDI
           |     |
   0 1 2 3 4 5 6 7 8 9 

После

   STD
   REP MOVSB

RSI   RDI
 |     |          
   0 1 2 0 1 2 3 4 8 9

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

...