2013-10-09 8 views
0

код компилируется нормально [NASM]код падает во время исполнения (Монтаж)

Но как только я ввода моего первого значения он выходит из строя

Я не знаю, что случилось, цель состоит в том, чтобы строка ввода и вывода в обратной последовательности, в то время как все в цикле, чтобы повторить, если пользователь говорит да («Y» или «Y»)

**.DATA 
; Initialized Data Definitions 

strlength  EQU  40 
PromptStr  dd  "Please input a string (must be less than 40 characters long): ", 0 
OutputStr  dd  "The reverse string is: ", 0 
AgainStr  dd  "Would you like ot try again? ('Y' or 'y' for yes): ", 0 

.UDATA 
; Uninitialized Data Definitions 

string   resb strlength 

.CODE 
; Program Code 

.STARTUP 

nwln     ; start output at a new line 
PutStr  PromptStr 
nwln 
while: 
    GetStr    string 
    mov     EBX, string 

    loop_in: 
     push   dword[EBX] 
     add    EBX, 4 
     cmp    dword[EBX], 0 
     jnz    loop_in 

    loop_out: 
     XOR    EBX, EBX 
     pop    EBX 
     PutCh   [EBX] 
     cmp    dword[EBX], 0 
     jnz    loop_out 

    nwln 
    PutStr    AgainStr 
    GetStr    EBX 
    mov     AL, [EBX] 
    cmp     AL, 'Y' 
    jz     while 
    cmp     AL, 'y' 
    jz     while 

    Pause 


.EXIT** 

Я изменил первый цикл для

loop_in: 
     mov    AL, [EBX] 
     push   byte[AL] 
     add    EBX, 4 
     cmp    byte[AL], 0 
     jnz    loop_in 

и им получать эту ошибку «ошибка: недопустимый эффективный адрес»

Когда я изменяю «байты»

loop_in: 
     push   byte[EBX] 
     add    EBX, 4 
     cmp    byte[EBX], 0 
     jnz    loop_in 

я получаю «ошибка: неправильное сочетание опкода и операндов»

для линии {добавьте EBX, 4}

Таким образом, я изменил

loop_in: 
     push   EBX 
     inc    EBX 
     cmp    byte[EBX], 0 
     jnz    loop_in 

    loop_out: 
     XOR    EBX, EBX 
     pop    EBX 
     PutCh   [EBX] 
     cmp    byte[EBX], 0 
     jnz    loop_out 

и теперь он собирает, и я получаю это далеко

Please input a string (must be less than 40 characters long): 
asdf 
fdsaêë 

, прежде чем он выходит из строя в окнах

+0

Используйте отладчик, ступая в инструкции машины. 'PutStr' не является инструкцией ассемблера. –

+0

с использованием файла макроса – BKreger

+0

Затем покажите файл макроса или, по крайней мере, ссылку на него. –

ответ

0

Может быть что-то подобное может работать:

loop_in: 
    mov    AX, [EBX] 
    push   AX   ; move two characters to the stack 
    inc    EBX 
    inc    EBX 
    cmp    AX, 0 
    jnz    loop_in 
    cmp    AL, 0 
    jnz    loop_in ; two end-of-string checks, 
           ; because we push two characters 


loop_out: 
    pop    AX 
    PutCh   AH 
    PutCh   AL 
    dec    EBX 
    dec    EBX 
    cmp    EBX, string 
    ja    loop_out 
+0

Он выходит из строя сразу после того, как окончательный обратный символ печатается на экране, поэтому я предполагаю, что что-то пойдет не так с выходом цикла – BKreger

+0

@chaosmatter: Разве вы не имеете в виду 'cmp AH, 0/jz loop_out' вместо' cmp AX, 0/jnz loop_in'? (если идея состояла в том, чтобы проверить, является ли любой из символов NUL) – Michael

+0

понял это, опубликовано в главных комментариях – BKreger

0

Как ты «Compile «это, поскольку мы не собираем источник сборки, мы собираем и произвольно связываем.

У меня нет файла макроса, поэтому здесь я использовал несколько функций из библиотеки C, но все это должно быть то же самое:

push dword [stdin] 
    push MAX_INPUT 
    push string 
    call fgets       
    add  esp, 4 * 3 

    ;~ fgets adds the NL char to string, replace with NULL 
    push string 
    call RemoveNL 

    mov  esi, string 
    xor  ebx, ebx 
PushChar: 
    movzx eax, byte[esi + ebx] 
    test eax, eax 
    jz  PopChar 
    push eax 
    inc  ebx 
    jmp  PushChar 

PopChar: 
    push fmtchar 
    push dword [stdout] 
    call fprintf       
    add  esp, 4 * 3  
    dec  ebx 
    jnz  PopChar 

    jmp  Done 

RemoveNL: 
    mov  esi, [esp + 4] 
    xor  ecx, ecx 
    dec  ecx 
.FindNL: 
    inc  ecx 
    cmp  byte [esi + ecx], 10 
    jne  .FindNL 
    mov  byte [esi + ecx], 0 
    ret  4 

Теперь для объяснения:

mov  esi, string 
    xor  ebx, ebx 
PushChar: 
    movzx eax, byte[esi + ebx] 
    test eax, eax 
    jz  PopChar 
    push eax 
    inc  ebx 
    jmp  PushChar 

Как только вы вызываете то, что вы вызываете, чтобы получить вход, строка содержит символы. Мы перемещаем адрес string в esi, ноль ebx для использования в качестве индекса в массиве символов. Сначала мы переместим байт из указателя в esi + ebx и переместим его в eax с нулевым расширением eax, пока мы находимся на нем, он перемещает значение ASCII char в младшие байты eax и выравнивает верхние неиспользуемые байты. Затем мы ищем терминатор NULL с test, и если он равен нулю в текущем индексе, мы делаем с нажатием значений в стек. Если значение не равно 0, мы нажимаем eax на стек и увеличиваем ebx (наш индекс) на один и продолжаем цикл.

PopChar: 
    push fmtchar 
    push dword [stdout] 
    call fprintf       
    add  esp, 4 * 3  
    dec  ebx 
    jnz  PopChar 

Там нет необходимости pop значение затем push снова в качестве параметра для нашей функции печати/макро, так как он уже в стеке и стек LIFO, последний символ толкнул готов к печати.Здесь вы видите только 2 параметра, нажатых для fprintf, но все же я настраиваю esp, как будто я нажал 3 параметра. Ну, мы удаляем печатный символ из стека, и следующий символ готов. Как мы узнаем, когда остановиться? Мы используем номер в ebx из нашего PushChar цикла и уменьшить это значение до тех пор, пока 0.

Выход: enter image description here

Смежные вопросы