I wanted to bootstrap Odin code like a kernel but the Odin compiler is producing code that is modifying memory off by one byte.
Compiling this Odin
entry :: proc() {
p := ([^]u8)(uintptr(0xB8000))
p[0] = '!'
}
Produces this assembly:
entry:
.cfi_startproc
movl $753664, %eax
movq %rax, -8(%rsp)
movq -8(%rsp), %rax
movb $33, (%rax)
retq
It doesn't modify the byte at 0xB8000 (start of VGA text buffer), but rather the byte before it. What stood out to me was the 32 bit movl, so I modified the assembly manually, pushing the address to the stack directly, which made it work correctly. Any ideas as to why? I'm not familiar with low level stuff.
entry:
.cfi_startproc
movq $753664, -8(%rsp)
movq -8(%rsp), %rax
movb $33, (%rax)
retq
Compiling a similar function in C produced this asm, which also works correctly:
entry:
push %rbp
mov %rsp,%rbp
movq $0xb8000,-0x8(%rbp)
mov -0x8(%rbp),%rax
movb $0x21,(%rax)
pop %rbp
ret