I am looking for an easy way to manage file opening and closing in x86-64 assembly on linux. I thought the easiest way would be to write a c file containing functions that I could call without having to worry about stability. So I wrote this function :
struct PORT open_port(char *filename, int mode) {
struct PORT port;
port.p = 0;
if (mode) {
if (filename == "stdout")
port.f = stdout;
else
port.f = fopen(filename, "wb+");
} else {
if (filename == "stdin")
port.f = stdin;
else
port.f = fopen(filename, "rb");
}
return port;
}
And then I read the port like so:
char readchar(struct PORT *port)
{
char r;
if ((*port).p)
r = (*port).p;
else
r = fgetc((*port).f);
(*port).p = 0;
return r;
}
Where PORT.p is a char which contains the character at the current position and PORT.f a file pointer. Then I call those function in my assembler code by putting the parameters in %rdi and %rsi.
Everything works as expected when I am reading an ordinary file, but the stdin support doesn't work. I know stdin is supposed to be the value 0 and when I debug my code, I can see that the value holding the file pointer is indeed 0, but when the code gets to the fgetc() call, it seg faults. If I write plainly fgetc(0); in my function, there is also a segmentation fault. I don't get how the fgetc() function can tell the difference between the stdin and a normal 0.
How can I read stdin using this (or a very similar pattern)? Or if it's all wrong, what should I do to open files in x64 assembly? There is certainly something I am not getting regarding how it works, help would be greatly appreciated.
(For those who are wondering what's the point of this all: it's to be able to read the next character without [in appearance] moving the file pointer, so there is a peekchar function that sets PORT.p if it's unset, so p can hold the value until it's read)