2

I want to create a menu where the user can just press a button and choose from the options on the screen.

I've tried using getchar(), fgets(stdin), gets(), and even getch().

I've turned to using some inline assembly to get ONE character from stdin. The code i've used is as follows :

char io::u_i() {
    char a;
    __asm__("INT 0x21;"     // Interruption vector for input
            "MOV %1, %0;"   // Move from stdin to a
            : "=r" (a)      // Output variable
            : "r" (stdin)   // Input variable
            : "%1"          // Obfuscated registers
            );
    return a;
}

If I've understood well enough how G++ compiles assembly, it should send an interrupt vector (0x21 being the one I found online to ask a key press), then move what is in the register where G++ will take the input (so stdin in this case) to the register where G++ will take the output.

I've done a bit of regular assembly before (AT&T syntax), without asking for user input. So this is a bit of a new territory for me. G++ tells me there is an error at this point in the code :

sources/io.cpp:7:11: error: invalid operand for instruction
                __asm__("INT 0x21;"     // Interruption vector for input
                        ^
<inline asm>:1:6: note: instantiated into assembly here
        INT 0x21;MOV %rcx, %r8b;
            ^~~~~
sources/io.cpp:7:11: error: unknown use of instruction mnemonic without a size suffix
                __asm__("INT 0x21;"     // Interruption vector for input
                        ^
<inline asm>:1:11: note: instantiated into assembly here
        INT 0x21;MOV %rcx, %r8b;
                 ^

But in my introduction to assembly, there was no need for anything else than INT 0x21;, so I don't see what G++ expects from me here. Is there a specific compiler option for inline ASM with AT&T syntax ?

Is my piece of code even going to do what I expect from it ?

P.S. : If it can help you in any way, I am compiling this on macOS Sierra, and here is the output of g++ --version :

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.38)
Target: x86_64-apple-darwin16.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
  • 1
    In AT&T syntax immediate values like 0x21 require a `$` to be prepended to it. `Int $0x21`. But my bigger concern is that this won't run as a user application under an operating system like Linux or OSX (you seem to be on OSX).. `int $0x21` is normally a DOS interrupt. What environment are you intending to run this program in? Is the operating system development? – Michael Petch Apr 17 '17 at 19:25
  • weird, `kbhit()` + `getch()` should've been enough – Ap31 Apr 17 '17 at 19:29
  • Other issues. With inline extended asm all register names have to have a `%%` instead of just `%`. So `%rcx` should be `%%rcx` etc. As well you can move a 64-bit register to an 8 bit register which you are trying to do with `MOV %rcx, %r8b` . – Michael Petch Apr 17 '17 at 19:29
  • @MichaelPetch I am going to run this program under an OS X environment, as well as Ubuntu. This will be a CLI application (it's a project for university). And for the MOV instruction, I just assumed I would need to copy what was in stdin to the output variable (as I said, I haven't had a chance to ask for user input in a assembly program, so this is all new to me) – Thibault de Villèle Apr 17 '17 at 19:32
  • This won't run under OS/X. It will fault on `int $0x21` because that isn't a supported interrupt on either OSX or Linux. – Michael Petch Apr 17 '17 at 19:33
  • @MichaelPetch Well is there an equivalent interrupt vector for OS X / Unix ? I've tried all day yesterday to look for one, but haven't found anything. – Thibault de Villèle Apr 17 '17 at 19:34
  • 1
    You can't use MS-DOS APIs on Mac OS. To remove the need for the user to press enter before your program sees a user's input you need to use `tcsetattr` to change to non-canonical input processing. You don't need to use assembly for this. See https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/tcsetattr.3.html#//apple_ref/doc/man/3/tcsetattr Alternatively you might want to use the curses library which has a simpler interface for this kind of thing. – Ross Ridge Apr 17 '17 at 19:35
  • 1
    If you are looking for an OS/X and Linux solution you may wish to look at this SO answer: http://stackoverflow.com/a/7469410/3857942 . It uses `termios` functionality modifying the terminal io settings to create `getch` like functionality. – Michael Petch Apr 17 '17 at 19:37
  • @MichaelPetch Thanks. So I don't need any special g++ flags for compiling ? I already use `-std=c++11` for some of my code. Also, does this changes only the input method on terminal ? I wouldn't want to change anything else on the terminal settings without knowing it. – Thibault de Villèle Apr 17 '17 at 19:52
  • Ah, g++ will require some modifications but the functionality is still available. – Michael Petch Apr 17 '17 at 19:56
  • @MichaelPetch Well thanks a lot, this solved my problem ! Adjusted the code in the thread you linked to my problem, and now everything works perfectly ! Will mark as a duplicate of said thread, and solved. – Thibault de Villèle Apr 17 '17 at 19:58

1 Answers1

1

OK, found a solution that doesn't need assembly code.

It s basically a slight tweak of this thread to make it compile in C++ under the g++ compiler.

Just need to change the name of the variable called new in the code to make it compile under g++. Thanks for the help, and I hope this can answer someone else's problems as well.

Community
  • 1
  • 1