2015-11-13 6 views
0

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

INCLUDE Irvine32.inc 

.data 
buffer byte 20 DUP(0) 
byteCount DWORD ? 

Question byte "Please enter your name." ,0 
Greeting byte "Hello " ,0 
Statement byte " Here is your name backwards" 

.code 
main proc 


mov edx , OFFSET Question 
call WriteString 
call CRLF 
Call CRLF 

mov edx, OFFSET buffer 
mov Ecx, SIZEOF buffer 
call ReadString 

push edx 
mov EDX ,OFFSET greeting 
Call WriteString 
pop edx 
call WriteString 
Call CRLF 
Call CRLF 

Как вы можете видеть, это успешно принимает введенный пользователем ввод и отображает его, но Im действительно изо всех сил пытается его перевернуть.

Я пробовал здесь, что я скопировал из книги из главы об обратных строках.

; Push the name on the stack. 

mov ecx,nameSize 
mov esi,0 

L1: movzx eax,aName[esi] ; get character 
push eax    ; push on stack 
inc esi 
loop L1 

; Pop the name from the stack in reverse 
; and store it in the aName array. 

mov ecx,nameSize 
mov esi,0 

L2: pop eax    ; get character 
mov aName[esi],al  ; store in string 
inc esi 
loop L2 

Invoke ExitProcess,0 
main endp 
end main 

но я получаю как вывод ничего.

он говорит: «Привет, (вашеимя здесь)»

он говорит: «это ваше имя в обратном направлении»

ив пытался почти все разные ипостаси этого я могу думать и безрезультатно. im в конце моей «строки» здесь

+0

Хорошо, что обратная строка будет основной частью вашего задания. Можете ли вы показать/рассказать нам то, что вы пробовали, что не удалось? –

+0

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

+0

Да, я изменил все ссылки так, чтобы это было сеткой. –

ответ

2

Это противоречит моему лучшему суждению, поскольку фрагмент кода для реверса даже не был интегрирован в код, созданный исходным плакатом. Имена переменных различаются. Быстрая и грязная интеграция кода заключается в создании переменной nameSize, которая содержит количество символов, прочитанных с вызова ReadString. ReadString (часть библиотеки Irvine32) возвращает количество символов, записанных в регистре EAX.

В разделе .data добавить переменную:

nameSize DWORD ? 

После того, как содержимое ReadString ход EAX регистра в nameSize. Этот код:

mov edx, OFFSET buffer 
mov Ecx, SIZEOF buffer 
call ReadString 

Должно быть:

mov edx, OFFSET buffer 
mov Ecx, SIZEOF buffer 
call ReadString 
mov nameSize, eax  ; EAX contains number of characters read into buffer 

В фрагменте кода для реверсирования кода удалите строки со дна в конце процедуры и т.д. Они не нужны, так как мы будем это делать в нашем исходном коде.

Invoke ExitProcess,0 
main endp 
end main 

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

INCLUDE Irvine32.inc 

.data 
buffer byte 20 DUP(0) 
byteCount DWORD ? 
nameSize DWORD ? 

Question byte "Please enter your name." ,0 
Greeting byte "Hello " ,0 
Statement byte " Here is your name backwards" 

.code 
main proc 

    mov edx , OFFSET Question 
    call WriteString 
    call CRLF 
    Call CRLF 

    mov edx, OFFSET buffer 
    mov Ecx, SIZEOF buffer 
    call ReadString 
    mov nameSize, eax 

    push edx 
    mov EDX ,OFFSET greeting 
    Call WriteString 
    pop edx 
    call WriteString 
    Call CRLF 
    Call CRLF 

    mov ecx,nameSize 
    mov esi,0 

L1: movzx eax,buffer[esi] ; get character 
    push eax    ; push on stack 
    inc esi 
    loop L1 

    ; Pop the name from the stack in reverse 
    ; and store it in the aName array. 

    mov ecx,nameSize 
    mov esi,0 

L2: pop eax    ; get character 
    mov buffer[esi],al  ; store in string 
    inc esi 
    loop L2 


    mov EDX ,OFFSET buffer 
    call WriteString   ; Write the reversed string that is now in buffer 

    exit 
main ENDP 
END 

Если вы получаете ссылки ошибки, вы не можете быть ссылками во всех предварительных библиотеках. Попробуйте добавить эти строки в верхней части программы:

INCLUDE Irvine32.inc 
INCLUDELIB Irvine32.lib 
INCLUDELIB user32.lib 
INCLUDELIB kernel32.lib 

Я должен отметить, что это очень неэффективный способ изменить строку, если вы не против уничтожения оригинала. Это можно сделать без вторичного буфера в стеке, изменив строку на месте.

+1

Реверсирование последовательности из 16, 32 или 64-битных целых чисел путем нажатия на стек фактически является умным. Затем он находится прямо в стеке, в обратном порядке, от '[esp]' до '[esp + count * size]'. Повторяя это снова, смешно. И так как нет никакого способа вставить один байт в стек ('push [m8]' или что-то еще), вы правы, что эта идея ужасна для строк. Он будет работать, если вы загрузили 2, 4B или 8B за раз и использовали 'bswap', чтобы отменить эти байты перед нажатием. (Или «movbe» для загрузки с заменой «на лету» (Atom, Haswell и Jaguar)). –

+1

@PeterCordes Это был код, с которым OP пытался интегрироваться (в обновленном вопросе) и хотел получить помощь только для получения основ (домашнее задание). Вопрос заключается в том, чтобы/было пограничное голосование закрываться в зависимости от того, как вы хотите определить _разумное усилие. Если бы я предоставил свой ответ, я хотел бы получить почетное достоинство от их учреждения ;-) –

+0

+ Michael Petch Спасибо, но я не могу получить ваш код даже для компиляции. Я получаю две ошибки при его создании. 1 неразрешенные внешние и нерешенные внешние symbol_mainCRTStartup –

0

На высоком уровне:

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

Делать это без выделения нового буфера можно также, но следует избегать в целом из-за стоимости вызова системного вызова (который вам нужно будет сделать после каждого символа)

section .data 

prompt  db "Please enter your name: ", 10 
length  equ $ - prompt 
text  times 255 db 0 
buffer  times 255 db 0 

Enter your text 
section .text 
global main 
main: 
    mov rax, 1 
    mov rdi, 1 
    mov rsi, prompt 
    mov rdx, length 
    syscall 

    mov rax, 0 
    mov rdi, 0 
    mov rsi, text 
    syscall 

    mov rcx, rax ; rcx will be the character counter. 
    mov rsi, text ; a pointer to the current character. Start from the beginning. 
    add rsi, rcx 
    dec rsi  ; Remember the 0-index 
    mov rdi, buffer 

;; This subroutine is also SUB-optimal if your teacher demands 
;; performance, look into the advantages of `lea` and a simple 
;; rep;scas loop as well. 
process_loop: 
    mov bl, [rsi]    ; Now copy from back to front 
    mov [rdi], bl 
    inc rdi 
    dec rsi 
    dec rax 
    jnz process_loop 

    mov rax, 1     ; And print the string 
     mov rdi, 1 
     mov rsi, buffer 
     mov rdx, rcx 
     syscall 

exit: 
    mov  rax, 60 
    mov  rdi, 0 
    syscall 
+0

Это 64-разрядный код для Linux с использованием синтаксиса NASM (и, по-видимому, с использованием 32-битных системных вызовов). Исходный плакат использует 32-битный код в Windows с использованием синтаксиса MASM. Я не думаю, что это дает большую часть ответа в среде, которую использует OP. –

+0

Я согласен и заметил, что я также не думаю, что это очень щедро для первоначального плаката, чтобы предоставить им точный ответ, который они могут скопировать для своей домашней работы. Излишне говорить, что перенос этой логики является тривиальным и заставит пользователя быть знакомым с концепциями (и, возможно, изучать семантику на MASM, например, 'byte ptr'). –

+0

. Вы случайно увидели меня в предисловии к моему ответу с помощью _This против моего лучшего суждения , То, что я не хотел поставлять, было более эффективным методом на месте, и я бы надеялся, что профессор даст лучшие оценки. Именно поэтому в моем эпилоге я сделал комментарий к этому вопросу;) У пользователя была функция функции разворота, которая просто нужна интеграция. Не так, как я много писал о новом коде (3 строки) –