flat assembler
Message board for the users of flat assembler.

Index > High Level Languages > C# console I/O to ASM converter

Author
Thread Post new topic Reply to topic
FlierMate



Joined: 21 Jan 2021
Posts: 219
FlierMate 24 Apr 2021, 08:41
You use "I" for input followed by variable name (case-sensitive)
You use "O" for output (optionally variable name)

Look, my C# 114-line converter use this as input file:
Code:
O Hello World
O Press key in your name
I a
O Hi,
O a
O A
O Variable name is case-sensitive
O a
O Can you please enter your age?
I A
O Your age is...
O A    


Then, generate the following programmatically:

Code:
format PE console
entry start


include 'win32a.inc'


section '.data' readable writable
    _stdin          dd ?
    _stdout         dd ?
    _dummy          dd ?


section '.code' code readable writable executable
    _S0000          db 'Hello World',13,10,0
    _S0001          db 'Press key in your name',13,10,0
    _S0002          rb 256
    _S0003          db 'Hi,',13,10,0
    _S0004          db 'a',13,10,0
    _S0005          db 'A',13,10,0
    _S0006          db 'Variable name is case-sensitive',13,10,0
    _S0007          db 'a',13,10,0
    _S0008          db 'Can you please enter your age?',13,10,0
    _S0009          rb 256
    _S0010          db 'Your age is...',13,10,0
    _S0011          db 'A',13,10,0
    _L0000          dd 14
    _L0001          dd 25
    _L0002          dd ?
    _L0003          dd 6
    _L0004          dd 4
    _L0005          dd 4
    _L0006          dd 34
    _L0007          dd 4
    _L0008          dd 33
    _L0009          dd ?
    _L0010          dd 17
    _L0011          dd 4


start:
           invoke   GetStdHandle, -10
           mov      dword [_stdin], eax
           invoke   GetStdHandle, -11
           mov      dword [_stdout], eax


           invoke   WriteConsole, dword [_stdout], _S0000, [_L0000], _dummy, 0
           invoke   WriteConsole, dword [_stdout], _S0001, [_L0001], _dummy, 0
           invoke   ReadConsole, dword [_stdin], _S0002, 255, _L0002, 0
           invoke   WriteConsole, dword [_stdout], _S0003, [_L0003], _dummy, 0
           invoke   WriteConsole, dword [_stdout], _S0002, [_L0002], _dummy, 0
           invoke   WriteConsole, dword [_stdout], _S0005, [_L0005], _dummy, 0
           invoke   WriteConsole, dword [_stdout], _S0006, [_L0006], _dummy, 0
           invoke   WriteConsole, dword [_stdout], _S0002, [_L0002], _dummy, 0
           invoke   WriteConsole, dword [_stdout], _S0008, [_L0008], _dummy, 0
           invoke   ReadConsole, dword [_stdin], _S0009, 255, _L0009, 0
           invoke   WriteConsole, dword [_stdout], _S0010, [_L0010], _dummy, 0
           invoke   WriteConsole, dword [_stdout], _S0009, [_L0009], _dummy, 0
           invoke   ExitProcess, 0


section '.idata' import readable writable
    library kernel32,'KERNEL32.DLL'


    import kernel32,\
           GetStdHandle, 'GetStdHandle', \
           WriteConsole, 'WriteConsoleA', \
           ReadConsole, 'ReadConsoleA', \
           ExitProcess,'ExitProcess'
    


Result in command-prompt window:

Code:
C:\FASM>1
Hello World
 Press key in your name
 wong
Hi,
 wong
A
 Variable name is case-sensitive
 wong
Can you please enter your age?
 23
Your age is...
 23

C:\FASM>    


Cute?

My HLL (C#) source : (not tested thoroughly, just done simple test)

Code:
using System;
using System.IO;

namespace Pancake
{
    public class Program
    {        
        public static void Main(string[] args)
        {
            const string NUL = "_$0";
            string[] Header = new string[] 
            { 
                "format PE console", 
                "entry start", "\r\n", 
                "include 'win32a.inc'", "\r\n",
                "section '.data' readable writable",
                "    _stdin          dd ?",
                "    _stdout         dd ?",
                "    _dummy          dd ?","\r\n",
                "section '.code' code readable writable executable"
            };
            string[] Body = new string[]
            {
                "\r\n", "start:",
                "           invoke   GetStdHandle, -10",
                "           mov      dword [_stdin], eax",
                "           invoke   GetStdHandle, -11",
                "           mov      dword [_stdout], eax", "\r\n"
            };
            string[] Footer = new string[] 
            {
                "           invoke   ExitProcess, 0","\r\n",
                "section '.idata' import readable writable", 
                "    library kernel32,'KERNEL32.DLL'", "\r\n",
                "    import kernel32,\\",
                "           GetStdHandle, 'GetStdHandle', \\",
                "           WriteConsole, 'WriteConsoleA', \\",
                "           ReadConsole, 'ReadConsoleA', \\",
                "           ExitProcess,'ExitProcess'"  
            };

            if ((args.Length > 0) && (File.Exists(args[0])))
            {
                string[] InputFile = File.ReadAllLines(args[0]);
                string[] StdIn = new string[InputFile.Length];
                string[] StdOut = new string[InputFile.Length];
                int LineCount = 0;                

                foreach (string InputLine in InputFile)
                {
                    string Line = InputLine.Trim();

                    if (Line.ToUpper().StartsWith("I "))
                    {
                        StdIn[LineCount] = Line.Substring(2);
                        StdOut[LineCount] = NUL;
                        LineCount++;
                    }
                    else if (Line.ToUpper().StartsWith("O "))
                    {
                        StdOut[LineCount] = Line.Substring(2);
                        StdIn[LineCount] = NUL;
                        LineCount++;
                    }
                }

                string[] VarName = new string[LineCount];
                string[] VarLen = new string[LineCount];
                string[] Code = new string[LineCount];

                if (LineCount > 0)
                {             
                    for (int a = 0; a < LineCount; a++)
                    {
                        if (StdIn[a] != NUL)
                        {
                            VarName[a] = "    _S" + a.ToString("D4") + "          rb 256";
                            VarLen[a] = "    _L" + a.ToString("D4") + "          dd ?";
                            Code[a] = "           invoke   ReadConsole, dword [_stdin], _S" + a.ToString("D4") + ", 255, _L" + a.ToString("D4") + ", 0";
                        }
                        if (StdOut[a] != NUL)
                        {
                            VarName[a] = "    _S" + a.ToString("D4") + "          db '" + StdOut[a] + "',13,10,0";
                            VarLen[a] = "    _L" + a.ToString("D4") + "          dd " + (StdOut[a].Length + 3).ToString();
                            for (int b = 0; b < LineCount; b++)
                            {
                                if ((StdOut[a] == StdIn[b]) && (b < a))
                                {
                                    Code[a] = "           invoke   WriteConsole, dword [_stdout], _S" + b.ToString("D4") + ", [_L" + b.ToString("D4") + "], _dummy, 0";
                                    break;
                                }
                                else
                                    Code[a] = "           invoke   WriteConsole, dword [_stdout], _S" + a.ToString("D4") + ", [_L" + a.ToString("D4") + "], _dummy, 0";
                            }
                        }
                    }
                }

                string FileName = args[0] + ".ASM";
                File.WriteAllLines(FileName, Header);
                File.AppendAllLines(FileName, VarName);
                File.AppendAllLines(FileName, VarLen);
                File.AppendAllLines(FileName, Body);
                File.AppendAllLines(FileName, Code);
                File.AppendAllLines(FileName, Footer);

                Console.WriteLine(FileName + " created successfully.");
            }

            Console.WriteLine("Press Enter to quit...");
            Console.ReadLine();
        }
    }
}    
Post 24 Apr 2021, 08:41
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20295
Location: In your JS exploiting you and your system
revolution 24 Apr 2021, 11:07
I think that show the difficulty of creating good asm code from an HLL.

Otherwise, it's a good start.
Post 24 Apr 2021, 11:07
View user's profile Send private message Visit poster's website Reply with quote
FlierMate



Joined: 21 Jan 2021
Posts: 219
FlierMate 05 May 2021, 19:50
revolution wrote:
I think that show the difficulty of creating good asm code from an HLL.

Otherwise, it's a good start.


Thanks, I have been described as someone who has zero knowledge in parser and lexer..... Embarassed
Post 05 May 2021, 19:50
View user's profile Send private message Reply with quote
FlierMate1



Joined: 31 May 2022
Posts: 118
FlierMate1 01 Jul 2022, 00:06
FlierMate wrote:
revolution wrote:
I think that show the difficulty of creating good asm code from an HLL.

Otherwise, it's a good start.


Thanks, I have been described as someone who has zero knowledge in parser and lexer..... Embarassed


I use a lexer and parser written in Python from jayconrod.com.

With the "source code" below:
Code:
n := 5;
p := 1;
while n > 0 do
  p := p * n;
  n := n - 1
end
    


It gets analyzed as:

Code:
('n', 'ID')
(':=', 'RESERVED')
('5', 'INT')
(';', 'RESERVED')
('p', 'ID')
(':=', 'RESERVED')
('1', 'INT')
(';', 'RESERVED')
('while', 'RESERVED')
('n', 'ID')
('>', 'RESERVED')
('0', 'INT')
('do', 'RESERVED')
('p', 'ID')
(':=', 'RESERVED')
('p', 'ID')
('*', 'RESERVED')
('n', 'ID')
(';', 'RESERVED')
('n', 'ID')
(':=', 'RESERVED')
('n', 'ID')
('-', 'RESERVED')
('1', 'INT')
('end', 'RESERVED')

Result(CompoundStatement(CompoundStatement(AssignStatement(n, IntAexp(5)), AssignStatement(p, IntAexp(1))), WhileStatement(RelopBexp(>, VarAexp(n), IntAexp(0)), CompoundStatement(AssignStatement(p, BinopAexp(*, VarAexp(p), VarAexp(n))), AssignStatement(n, BinopAexp(-, VarAexp(n), IntAexp(1)))))), 25)    


The first half is lexer, the second half is parser. I think it build AST (abstract syntax tree).

Pretty close to what I want, but still some difficulty to generate Assembly code based on the above.
Post 01 Jul 2022, 00:06
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.