assemblyfasmsasm

I Can't figure out what I must push to the stack before calling `_getch` in FASM


I'm using the SASM IDE by Dmitry Manushin to write a program in FASM. My code is as follows:

format ELF

section '.data' writeable
    msg db 'Hello, world of Flat ASM!',  0Dh, 0Ah, 00h ; terminate with null string
    buffer rb 20
    inp_buf_size rw 1
    pkey db 'Press any key to exit ...', 0h
    formatStr db "%s", 0

section '.text' executable
public _main
extrn _printf
extrn _getch
extrn _getche
_main:
    mov ebp, esp; for correct debugging
    push msg ; push message onto the stack
    push formatStr ; push formatter onto the stack
    call _printf ; call the printf method to print the message
    add esp, 8 ; clean up
    xor eax, eax
    ; press any key to exit
    mov ebp, esp; for correct debugging
    push pkey ; push message onto the stack
    push formatStr ; push formatter onto the stack
    call _printf ; call the printf method to print the message
    add esp, 8
    xor eax, eax
    
    ; get input here, using getch or getche (how? What must be pushed)
    ; mov ebp, esp; for correct debugging
    ; push buffer
    ; call _getch
    ; add esp, 8
    ; xor eax, eax
    
    ret

Printing the "Hello, world ..." and "Press any key ..." code works as expected. What I'm stuck on is how I go about getting the program to wait for/read a single character into the buffer using _getch. (What, if anything, should I push onto the stack before calling _getch?) I've tried moving values into ah and using interrupts, but this causes the program to crash.


Solution

  • There are a few things going on here format ELF tells FASM to create a Linux object file. Which feels a little odd because you are running Windows. But what makes it work is that SASM is using the MinGW version of the Linux gcc toolchain to create the executable. Which means you can write some Linux assembly but not everything can be Linux syntax.

    Another issue is that getch is not POSIX so could be causing problems, use getchar instead.

    And lastly windows does not exit programs by using return values in eax. The

    xor eax, eax
    ret
    

    part will hang in Windows because of this. A safe way to do it is call _ExitProcess passing it 0 on the stack.

    It appears that SASM expects any input to be entered into the input box beforehand and because of that does not wait for the _getchar. I left it in to show how it would work if SASM did not do this. Running similar code assembled directly using FASM works as expected.

    Putting that all together this we get this:

    format ELF
    
    section '.data' writeable
        msg db 'Hello, world of Flat ASM!',  0Dh, 0Ah, 00h
        pkey db 'Press any key to exit ...', 0h
        formatStr db "%s", 0
    
    public _main
    extrn _printf
    extrn _getchar
    extrn _ExitProcess
    
    section '.text' executable
    
    _main:
        push msg 
        push formatStr
        call _printf
    
        push pkey
        push formatStr
        call _printf
    
        call _getchar
        push 0
        call _ExitProcess
    

    I removed the stack code for simplicity as this is only a hello world.