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
  • 37,963
  • 15
  • 156
  • 475
  • 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 <- if in your kernel you set up paged (virtual memory) mode and access an address that's not explained in the page tables, the CPU will call your page fault handler. (The handler can then also summon the accessed page into existence, but you will soon run out of physical memory if you keep doing that...) –  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