Переворачивание строки в MASM. Получение странного вывода

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

; Reverses an input string of at least 10 characters
; Author:  Nathan Smith
; Created: 10/26/2018
; Revisions:
; Date:             Modified by:

INCLUDE Irvine32.inc

.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD

.data
myString BYTE "abcdefghij", 0       ; original string
temp BYTE ?                         ; temporary string holder

.code
main PROC
    mov esi, SIZEOF myString    ; source index register
    mov ecx, SIZEOF myString    ; loop counter
    movzx eax, myString         ; moves string to temp holder
    mov temp, al
    mov edi, 0                  ; destination index register
L1:
    mov al, temp[esi]           ; moves last letter to al
    mov myString[edi], al       ; moves letter from al to myString
    dec esi                     ; decreases pointer by 1
    inc edi                     ; increases destination pointer by 1
    loop L1                     ; repeat for length of string

    mov edx, OFFSET myString
    call WriteString
    INVOKE ExitProcess,0
main ENDP
END main

Я не уверен, что происходит.

Я думаю, вы путаете указатель на строку и строку. Вы выделили отдельный байт для temp, но читаете из этого места в памяти, как если бы данных было больше 1. movzx eax, myString перемещает первый байт myString в eax, а ноль расширяет значение, чтобы заполнить EAX.

Michael Petch 27.10.2018 00:15

да, но у ассемблера нет термина string. Может, лучше вообще не объяснять. Дело в том, что имя переменной не может указывать на что-то другое, кроме своего исходного места. Это не C или около того.

Алексей Неудачин 27.10.2018 00:32

Даже если я перейду на mov al, myString, он сделает то же самое.

ndsmith 27.10.2018 01:02

@ndsmith Перепиши все по старинке

Алексей Неудачин 27.10.2018 01:34
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
686
1

Ответы 1

Длина строки должна учитывать нулевую индексацию, поэтому;

mov   esi, SIZEOF myString - 1         ; Should equal 8
mov   ecx, SIZEOF myString             ; Should equal 9

Завершающий символ 0x0 НУЛЕВОЙ необходимо записать в конец темп. Чтобы хотя бы немного оптимизировать, запись 4 NULL работает, поскольку EDI - это только 32-битный регистр.

xor   edi, edi
mov   temp[ecx],edi                    ; Writing 4 chars

; Instead of

mov   BYTE temp[ecx], 0

Единственное, что нужно изменить в вашем цикле:

@@:
mov   al, myString [edi]               ; Read char from source
mov   temp[esi], al                    ; and write to destination
dec   esi
inc   edi
loop  @B

Что происходило с вашей программой, так это то, что

movzx eax, myString
mov   temp, al

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

Если вы используете другой регистр для счетчика, который необходимо обнулить, эффективен mov temp[ecx], dl.

Peter Cordes 27.10.2018 07:38

Код @PeterCordes OP имеет огромное количество раздувания, я старался не отклоняться далеко от цели вопроса. Я сделал пример только для себя, который вошел в 23 байта против 57 оригинального сообщения.

Shift_Left 27.10.2018 07:48

Ага. Но поскольку вы упоминали об изменениях, вам не нужно создавать хранилище двойных слов, которое включает 3 байта после конца того, что вы в противном случае написали бы. В любом случае, вы забыли еще одну серьезную ошибку: temp BYTE ? OP имеет только 1-байтовый буфер для места назначения.

Peter Cordes 27.10.2018 08:27

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