0

I'm trying to use the assembly inline code in C with gcc, to use the interrupt 21 with ah = 07h to make a getchar without echo. This is my code(the main):

...
int main(int argc, char *argv[])
{
    int t, x, y;
    char input;                
    asm(
        "movb $0x01, %%ah\n\t"
        "int $0x21\n\t"
        "movb %%al, %0"
        : "=r" (input) 
    );
    printf("Character: %c\n", input);
    return 0;
}
...

But it doesn't work, it compiles successfully but it doesn't do anything.

  • 1
    Which platform are you using? This code looks like code for AT&T-style assemblers. Interrupt 21 only works on DOS. – fuz Nov 23 '12 at 19:26
  • I'm on Linux. There is an universal interrupt for I/O? –  Nov 23 '12 at 19:28
  • @PizziraniLeonardo One of a full-service OS's primary tasks is to abstract away the low level details of (well, lots of things including) IO, so no. The fact that you can do that is DOS is a hint: DOS is not a full service OS; it is a bit more than a loader, but only a bit. – dmckee --- ex-moderator kitten Nov 23 '12 at 19:37
  • @PizziraniLeonardo: A universal interrupt? Funny. :) No, each OS sets up interrupts however it likes -- and they seem to like to be as different as possible. The low-level code to output a char in DOS looks almost nothing like the code to do so in Linux, and AFAIK, Windows would prefer (and probably enforces) that you not use interrupts at all. – cHao Nov 23 '12 at 19:37
  • I am so frustrated, I want make a little ascii game in C "simplest possible", but if I can't neither take a char without an echo or a newline. I will post a new question to find how to send a newline to the fgetc() instead of assembly. Thanks at all =) –  Nov 23 '12 at 19:44
  • 1
    @PizziraniLeonardo Now if you had said what you wanted to do, instead of how you thought you wanted to do it we could have told you *"Use `ncurses`."* right away. For instance: http://codegolf.stackexchange.com/questions/375/build-an-engine-for-a-maze-game/922#922 . – dmckee --- ex-moderator kitten Nov 23 '12 at 20:03
  • Thanks, beatiful obfuscated game *-* –  Nov 23 '12 at 20:09

3 Answers3

1

First of all you mixed an AT&T syntax with DOS int. so here are answers for each platform:

1.DOS: http://msdn.microsoft.com/en-us/library/5f7adz6y(v=vs.71).aspx

__asm mov ah,01
__asm int 21

Now al contains the read byte. As explained in here.

If you want to pass al to the char input use the right offset to stack pointer esp - <the offset> to reach the address of input and set to it the read value by calling mov byte [esp-offset], al.

2.LINUX:

The way you write the assembly is AT&T style so please check this out.

static inline
unsigned read_cr0( void )
{
    unsigned val;
    asm volatile( "mov %%cr0, %0"
                  : "=r"(val) );
    return val;
}
0x90
  • 39,472
  • 36
  • 165
  • 245
  • I know, in fact, I tried to move the al value into my input var. =) –  Nov 23 '12 at 19:37
  • You should use volatile as well, and declare char input as the first variable on the stack in the main function then the offset is obvious. – 0x90 Nov 23 '12 at 19:46
  • Oh, I saw the half version of your answer, sorry! –  Nov 23 '12 at 19:51
  • I got this: 1.c: Assembler messages: 1.c:19: Error: unsupported for `mov' –  Nov 23 '12 at 19:57
  • @PizziraniLeonardo What did you compiled? on what OS ? which compiler? there are few uncertainties in your questions. – 0x90 Nov 24 '12 at 07:14
0

From the informations you give, it seems that you are programming on a platform different from DOS. Interrupt 21 only works on DOS. For linux, have a look at the libraries ncurses and readline for advanced terminal tricks. If you want to do something more low-level, you might also be interested in the ANSI escape sequences. They give you a way to interact with the terminal.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • The point it's just that I don't want to interact with the terminal. =) –  Nov 23 '12 at 19:38
  • 1
    @PizziraniLeonardo: You're trying to control the terminal without interacting with the terminal? Think about it for a second, and then tell me how much success you expect to have with that. :) Particularly considering you're probably not running on a hardware terminal at all -- the "terminal" in Linux is an abstraction that has precious little to do with hardware. – cHao Nov 23 '12 at 19:42
  • XD, no interaction meant "Only C interaction" –  Nov 23 '12 at 19:45
  • @PizziraniLeonardo: Linux provides virtual terminals that are effectively controlled by sending control codes much the same as you'd send chars. You might be able to send a control code to disable local echo. But you'd have far less trouble (both now and down the road) if you learn to use a library like ncurses. Among other things, it abstracts away the differences between terminal types (so you don't have to care whether you're running on the console or in PuTTY, for example). Different terminal types have different control codes, and you really don't want to manage all that yourself. – cHao Nov 23 '12 at 19:49
  • I know, it's a sort of challenge, I'm trying to use only stdio.h, stdlib.h and time.h XD –  Nov 23 '12 at 19:59
0

Instead of using inline assembler, which as others have pointed out is DOS-specific, why don't you just set your terminal to disable echo? See this answer to another question for details on how to do so.

Community
  • 1
  • 1
Brian Campbell
  • 322,767
  • 57
  • 360
  • 340
  • I tried low programming just because I don't want disable echo on terminal. =) –  Nov 23 '12 at 19:35
  • @PizziraniLeonardo If you follow the link I gave you, it shows how to save the current terminal settings, change them to disable echo, and then set them back when you're done. There isn't any other way to disable echoing on Linux (or other Unix) systems; you need to set the terminal mode, and then set it back when you're done. – Brian Campbell Nov 23 '12 at 19:40
  • Thanks, if I can't be able to find nothing short I will do this. =) –  Nov 23 '12 at 19:46