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)