nmagerko
nmagerko

Reputation: 6814

x86 NASM Assembly - Problems with the Stack

I am working on a program to simply take in a user's input twice, and then print the result out to the standard output at a later time. The problem I am having is that, when the result is returned from the input interrupt (in eax), I push it onto the stack for use later. I do this again for the second user input.

The code I have so far is:

%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

I get severe problems with spacing in the output, most likely because of how I handle the values returned in eax when I push/pop it. Is there any way to fix this/ am I doing this wrong?

Upvotes: 3

Views: 1299

Answers (2)

nmagerko
nmagerko

Reputation: 6814

Thanks to Matt and ott.

Here is the solution:

%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

Upvotes: 0

Matthew Slattery
Matthew Slattery

Reputation: 47058

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

I don't know what these sys.write and sys.read macros are expected to do for you, but the chances are that they load eax with the correct value before invoking a syscall with int 0x80, so you probably don't need to do it yourself. There's not much point in them otherwise...

(That's not the problem though; 4 and 3 are the correct syscall numbers for write and read respectively on 32-bit Linux x86.)

The actual problem is probably here:

    xor ecx, ecx
    mov eax, ecx
    push ecx

This looks wrong: you are exclusive-ORing ecx with itself, which sets it to zero. Then you're assigning ecx (which is now 0) to eax (which is the result of the syscall), so the result of the syscall gets thrown away. Then you're pushing ecx (which is still 0) onto the stack.

Still further on, you have:

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

...which is also odd: why zero ecx and edx with the xor instructions, when you're just going to reload them from elsewhere a couple of instructions further on?


I guess you may just have the operands of the mov the wrong way round. Instead of:

    xor ecx, ecx
    mov eax, ecx
    push ecx

...if you said:

    xor ecx, ecx
    mov ecx, eax
    push ecx

....you would at least successfully push the value that was in eax (the return code from the syscall) onto the stack, although it would be a lot simpler to just say:

    push eax

Finally: you ask the "name" question, and (assuming the above it fixed) push the resulting length on the stack. Then you ask the "color" question, and push the resulting length on the stack.

But then you print the "name" surprise, using the first value popped from the stack, which is the length you saved from the "color" question. (A stack is last-in-first-out!) Then you use print the "color" surprise using the length from the "name" question.

Upvotes: 1

Related Questions