1

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.

  • OS: Windows 10 x86_64
  • Assembly language: FASM (as included with SASM) -- $SOURCE$ $PROGRAM.OBJ$ -s $LSTOUTPUT$
  • ** Mode:** x86
  • Linker options: $PROGRAM.OBJ$ $MACRO.OBJ$ -g -o $PROGRAM$ -m32
rkhb
  • 14,159
  • 7
  • 32
  • 60
Agi Hammerthief
  • 2,114
  • 1
  • 22
  • 38

2 Answers2

0

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.

nash
  • 3,020
  • 6
  • 38
  • 53
0

I was actually trying to figure out how to get SASM to behave on Windows when I found your question, after I wrote my other answer I stumbled upon a way for it to be able to use native Windows FASM syntax. In the Build options check the "Disable linking" box and change the $PROGRAM.OBJ$ "Assembly options" parameter to $PROGRAM$. This will cause it to use the Windows FASM.exe to assemble an your exe and skip the Linux style object creation and gcc linking.

A big negative of this is that the debugger no longer works which is a deal killer for me.

To show what Windows FASM code looks like here's my hello world:

format PE console
entry _main
include '%fasm_inc%/win32a.inc'

section '.data' data readable

hello db 'Hello world!', 0

section '.text' code readable executable

_main:
    invoke _printf, hello
    invoke _getchar
    push eax
    invoke _putchar
    invoke _ExitProcess, 0

section '.idata' import data readable

library kernel32, 'kernel32.dll',\
    msvcrt, 'msvcrt.dll'

import kernel32,\
        _ExitProcess, 'ExitProcess'
import msvcrt,\
        _printf, 'printf',\
        _getchar, 'getchar',\
        _putchar, 'putchar'

I added the _putchar to show that the _getchar is using the text in the input box and that SASM does not wait for user input.

nash
  • 3,020
  • 6
  • 38
  • 53
  • 1
    Not having the debugger available to me is going to be a stumbling block, especially since I am learning FASM,so I'll stick with the MinGW toolchain for now. – Agi Hammerthief Feb 25 '20 at 08:40