Сборка NASM x86 - проблемы со стеком - PullRequest
3 голосов
/ 04 ноября 2011

Я работаю над программой, которая просто дважды вводит пользовательский ввод, а затем выводит результат на стандартный вывод. У меня проблема в том, что когда результат возвращается из входного прерывания (в eax ), я помещаю его в стек для использования позже. Я делаю это снова для второго пользовательского ввода.

Код, который у меня пока есть:

%include "system.inc" ; used for renaming of interrupts (sys.write and sys.read)

section .data
    greet:      db 'Hello!', 0Ah, 'What is your name?', 0Ah
    greetL:     equ $-greet     ;length of string
    colorQ:     db 'What is your favorite color?', 0Ah
    colorL:     equ $-colorQ 
    suprise1:   db 'No way '
    suprise1L:  equ 7
    comma:      db ', '
    commaL:     equ $-comma
    suprise3:   db ' is my favorite color, too!', 0Ah
    suprise3L:  equ $-suprise3


section .bss

name: resb 50
color: resb 50

section .text

    global _start
_start:


greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

    xor ecx, ecx
    mov eax, ecx
    push ecx

askcolor:
    mov eax, 4
    mov ebx, 1
    mov ecx, colorQ
    mov edx, colorL
    sys.write

getcolor:
    mov eax, 3
    mov ebx, 0
    mov ecx, color
    mov edx, 50
    sys.read

    xor ebx, ebx
    mov ebx, eax
    push ebx


thesuprise:
    mov eax, 4
    mov ebx, 1
    mov ecx, suprise1
    mov edx, suprise1L
    sys.write

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx    
    pop ecx
    sub ecx, 1
    mov edx, ecx

    mov eax, 4
    mov ebx, 1
    mov ecx, name
    mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, comma
    mov edx, commaL
    sys.write

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx
    pop ebx
    sub ebx, 1
    mov edx, ebx

    mov eax, 4
    mov ebx, 1
    mov ecx, color
    mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, suprise3
    mov edx, suprise3L
    sys.write

done:

    mov eax, 1  
    mov ebx, 0  
    sys.exit

У меня серьезные проблемы с интервалом в выходных данных, скорее всего из-за того, как я обрабатываю значения, возвращенные в eax , когда я нажимаю / выдвигаю его. Есть ли способ исправить это / я делаю это неправильно?

Ответы [ 2 ]

1 голос
/ 04 ноября 2011
greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

Я не знаю, что эти макросы sys.write и sys.read могут сделать для вас, но есть вероятность, что они загрузят eax с правильным значением перед вызовом системного вызова с int 0x80, так что вы вероятно, не нужно делать это самостоятельно. Иначе в них нет особого смысла ...

(Это не проблема; 4 и 3 являются правильными номерами системных вызовов для write и read соответственно в 32-битной Linux x86.)

Фактическая проблема, вероятно, здесь:

    xor ecx, ecx
    mov eax, ecx
    push ecx

Это выглядит неправильно: вы исключаете ИЛИ ecx с самим собой, что устанавливает его на ноль. Затем вы присваиваете ecx (который теперь равен 0) eax (который является результатом системного вызова), поэтому результат системного вызова отбрасывается. Затем вы помещаете ecx (который по-прежнему равен 0) в стек.

Еще дальше, у вас есть:

    xor ebx, ebx
    xor ecx, ecx
    xor edx, edx    
    pop ecx
    sub ecx, 1
    mov edx, ecx

... что также странно: почему ноль ecx и edx с инструкциями xor, когда вы просто собираетесь перезагрузить их из других мест, еще пару инструкций?


Полагаю, у вас просто могут быть операнды mov в неправильном направлении. Вместо:

    xor ecx, ecx
    mov eax, ecx
    push ecx

... если вы сказали:

    xor ecx, ecx
    mov ecx, eax
    push ecx

.... вы бы по крайней мере успешно поместили значение, которое было в eax (код возврата из системного вызова) в стек, хотя было бы намного проще просто сказать:

    push eax

Наконец: вы задаете вопрос «name» и (предполагая, что вышеупомянутое исправлено) помещаете полученную длину в стек. Затем вы задаете «цветной» вопрос и помещаете полученную длину в стек.

Но затем вы печатаете сюрприз «имя», используя первое значение, извлеченное из стека, которое является длиной, которую вы сохранили из вопроса о «цвете». (Стек - «первым пришел - первым обслужен!»). Затем вы печатаете «цветной» сюрприз, используя длину из вопроса «name».

0 голосов
/ 04 ноября 2011

Благодаря Мэтту и Отту.

Вот решение:

%include "system.inc"

section .data
    greet:      db 'Hello!', 0Ah, 'What is your name?', 0Ah
    greetL:     equ $-greet     ;length of string
    colorQ:     db 'What is your favorite color?', 0Ah
    colorL:     equ $-colorQ 
    suprise1:   db 'No way '
    suprise1L:  equ 7
    comma:      db ', '
    commaL:     equ $-comma
    suprise3:   db ' is my favorite color, too!', 0Ah
    suprise3L:  equ $-suprise3


section .bss

name: resb 50
color: resb 50

section .text

    global _start
_start:


greeting:
    mov eax, 4
    mov ebx, 1
    mov ecx, greet
    mov edx, greetL
    sys.write

getname:
    mov eax, 3
    mov ebx, 0
    mov ecx, name
    mov edx, 50
    sys.read

    sub eax, 1
    push eax

askcolor:
    mov eax, 4
    mov ebx, 1
    mov ecx, colorQ
    mov edx, colorL
    sys.write

getcolor:
    mov eax, 3
    mov ebx, 0
    mov ecx, color
    mov edx, 50
    sys.read

    sub eax, 1
    push eax


thesuprise:
    mov eax, 4
    mov ebx, 1
    mov ecx, suprise1
    mov edx, suprise1L
    sys.write

    xor eax, eax
    pop eax
    mov ecx, eax
    pop eax
    mov edx, eax
    push ecx

    mov eax, 4
    mov ebx, 1
    mov ecx, name
    ;mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, comma
    mov edx, commaL
    sys.write

    xor eax, eax
    pop eax
    mov edx, eax

    mov eax, 4
    mov ebx, 1
    mov ecx, color
    ;mov edx, edx
    sys.write

    mov eax, 4
    mov ebx, 1
    mov ecx, suprise3
    mov edx, suprise3L
    sys.write

done:

    mov eax, 1  
    mov ebx, 0  
    sys.exit
...