0

So I'm trying to read and write into memory in my own OS, so I'm first trying to get it working in a test program in linux, heres the code:

#include <stdio.h>
#include <stdlib.h>
char MemRead(short addr){
    char data;
    __asm__ __volatile__ ("mov (%%bx), %%dl" : "=d" (data) : "b" (addr));
    return data;
}

void MemWrite(short addr,char c){
    __asm__ __volatile__ ("mov %%dl, (%%bx)" : : "b" (addr), "d" (c));
}

int main() {
    char d;
    unsigned short addr=0xf0f0;
    MemWrite(addr, 'a');
    d=MemRead(addr);
    printf("Hello World,%c",d);
    return 0;
}

I tried to compile it with gcc [filename] (my platform is x86_64) and got the error

tmp.c: Assembler messages:
tmp.c:6: Error: `(%bx)' is not a valid base/index expression
tmp.c:12: Error: `(%bx)' is not a valid base/index expression 

And when I tried compiling it in x86 that the OS I'm making is in, with gcc -m32 [filename] it returned no error, but a segmentation fault happened during the MemWrite() functions assembly time.

Edit: The assembly part is aparently not necessary, but even without using assembly it still causes the segmentation fault.

Test code:

 int main() {
        char d;
        unsigned short *addr=0xf0f0;
        *addr = 'a';
        d=*addr;
        printf("Hello World,%c",d);
        return 0;
    }
phuclv
  • 32,499
  • 12
  • 130
  • 417
  • For the 32-bit case did you try to disassemble the code generated? Despite of that reading and writing values to memory does not require inline assembly. – U. Windl Aug 26 '21 at 10:25
  • What was that supposed to do? Write a byte to address -3856? The expected reaction to attempting that IS a segfault, so everything seems to be in order. –  Aug 26 '21 at 10:31
  • @Andreas, why do you try to write an answer on something you don't know anything about? Double % is the right way to refer to a specific register in gcc inline assembly. (Pretty much everything else about this is wrong, though.) – prl Aug 26 '21 at 11:02
  • @prl, Would you please tell me what's wrong with the new test code, i stopped using assembly and fixed the short to an unsigned short, but still get a segmentation fault – LucaRicardo Aug 26 '21 at 11:05
  • Why do you think the address 0xf0f0 should be accessible? – prl Aug 26 '21 at 11:06
  • @dratenik, I fixed it into an unsigned short, so the value is now positive but I still get the segmentation fault – LucaRicardo Aug 26 '21 at 11:06
  • @prl Why wouldn't it? Linux uses virtual memory so why wouldn't I be able to access the entire virtual memory of my own process from my own process? I can't even read it without a segmentaion error – LucaRicardo Aug 26 '21 at 11:08
  • Linux prevents access to addresses below about 4M to catch null pointer dereferences. – prl Aug 26 '21 at 11:12
  • 1
    "Linux uses virtual memory." Correct. But you can only write to areas that are mapped and writable. You have to ask the kernel (e.g. with brk, mmap) to have a range of addresses populated with something before you can access it. –  Aug 26 '21 at 11:14
  • @prl 0xf0f0 is 61680 in decimal (the variable is unsigned) so it's not under 4k, rigth and I also tried reading the number at the max value of an unsigned int – LucaRicardo Aug 26 '21 at 11:20
  • 2
    The vast majority of your 256 terabyte address space isn't mapped to anything. If you choose random addresses to try, the chances are that all of them will fault. – prl Aug 26 '21 at 11:20
  • @dratenik Reading didn't work either and if I understand correctly then the in the kernel code of the OS I'm working on I will be able to read memory of any address like that without any error, rigth? – LucaRicardo Aug 26 '21 at 11:24
  • Even in ring 0 you can only read addresses that are mapped. – prl Aug 26 '21 at 11:25
  • 2
    https://wiki.osdev.org/Paging –  Aug 26 '21 at 11:33
  • Re: that unsafe inline asm: [How can I indicate that the memory \*pointed\* to by an inline ASM argument may be used?](https://stackoverflow.com/q/56432259). Of course it's not useful anyway; you can cast pointers in C. Especially if you compile with `-fno-strict-aliasing` so you can point any pointer-type at any memory location. But also, you don't usually need or want to use 16-bit address-size in 32-bit mode; it's less efficient even if the address fits. – Peter Cordes Aug 26 '21 at 14:30

0 Answers0