I've been trying to develop a small OS and managed to switch into protected mode, in order to write C code instead of assembly, but since this means I can't use interrupt 10h anymore, I have to write chars to the video memory address. So I tried creating a new print function to easily print out whole strings instead of printing each char separately. That's where the problems came in, for some reason, while printing single chars with the printchar
function works, this new print function doesn't work, no matter what I try.
Here's my C Code:
void print(char* message, int offset);
void printChar(char character, int offset);
void start() {
printChar('M', 2);
print("Test String", 4);
while (1) {
}
}
void print(char* msg, int offset) {
for (int i = 0; msg[i] != '\0'; i++)
{
printChar(msg[i], (i * 2) + offset);
}
}
void printChar(char character, int offset) {
unsigned char* vidmem = (unsigned char*)0xB8000;
*(vidmem + offset + 1) = character;
*(vidmem + offset + 2) = 0x0f;
}
I then use these commands to convert my code to binary and put it onto the second sector of a floppy disk with sectedit
.
gcc -c test.c
objcopy -O binary -j .text test.o test.bin
Also here's the assembly code generated, when using objdump -d test.o
0000000000000000 <start>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 20 sub $0x20,%rsp
8: ba 02 00 00 00 mov $0x2,%edx
d: b9 4d 00 00 00 mov $0x4d,%ecx
12: e8 73 00 00 00 call 8a <printChar>
17: ba 04 00 00 00 mov $0x4,%edx
1c: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # 23 <start+0x23>
23: 48 89 c1 mov %rax,%rcx
26: e8 02 00 00 00 call 2d <print>
2b: eb fe jmp 2b <start+0x2b>
000000000000002d <print>:
2d: 55 push %rbp
2e: 48 89 e5 mov %rsp,%rbp
31: 48 83 ec 30 sub $0x30,%rsp
35: 48 89 4d 10 mov %rcx,0x10(%rbp)
39: 89 55 18 mov %edx,0x18(%rbp)
3c: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
43: eb 29 jmp 6e <print+0x41>
45: 8b 45 fc mov -0x4(%rbp),%eax
48: 8d 14 00 lea (%rax,%rax,1),%edx
4b: 8b 45 18 mov 0x18(%rbp),%eax
4e: 01 c2 add %eax,%edx
50: 8b 45 fc mov -0x4(%rbp),%eax
53: 48 63 c8 movslq %eax,%rcx
56: 48 8b 45 10 mov 0x10(%rbp),%rax
5a: 48 01 c8 add %rcx,%rax
5d: 0f b6 00 movzbl (%rax),%eax
60: 0f be c0 movsbl %al,%eax
63: 89 c1 mov %eax,%ecx
65: e8 20 00 00 00 call 8a <printChar>
6a: 83 45 fc 01 addl $0x1,-0x4(%rbp)
6e: 8b 45 fc mov -0x4(%rbp),%eax
71: 48 63 d0 movslq %eax,%rdx
74: 48 8b 45 10 mov 0x10(%rbp),%rax
78: 48 01 d0 add %rdx,%rax
7b: 0f b6 00 movzbl (%rax),%eax
7e: 84 c0 test %al,%al
80: 75 c3 jne 45 <print+0x18>
82: 90 nop
83: 90 nop
84: 48 83 c4 30 add $0x30,%rsp
88: 5d pop %rbp
89: c3 ret
000000000000008a <printChar>:
8a: 55 push %rbp
8b: 48 89 e5 mov %rsp,%rbp
8e: 48 83 ec 10 sub $0x10,%rsp
92: 89 c8 mov %ecx,%eax
94: 89 55 18 mov %edx,0x18(%rbp)
97: 88 45 10 mov %al,0x10(%rbp)
9a: 48 c7 45 f8 00 80 0b movq $0xb8000,-0x8(%rbp)
a1: 00
a2: 8b 45 18 mov 0x18(%rbp),%eax
a5: 48 98 cltq
a7: 48 8d 50 01 lea 0x1(%rax),%rdx
ab: 48 8b 45 f8 mov -0x8(%rbp),%rax
af: 48 01 c2 add %rax,%rdx
b2: 0f b6 45 10 movzbl 0x10(%rbp),%eax
b6: 88 02 mov %al,(%rdx)
b8: 8b 45 18 mov 0x18(%rbp),%eax
bb: 48 98 cltq
bd: 48 8d 50 02 lea 0x2(%rax),%rdx
c1: 48 8b 45 f8 mov -0x8(%rbp),%rax
c5: 48 01 d0 add %rdx,%rax
c8: c6 00 0f movb $0xf,(%rax)
cb: 90 nop
cc: 48 83 c4 10 add $0x10,%rsp
d0: 5d pop %rbp
d1: c3 ret
d2: 90 nop
d3: 90 nop
d4: 90 nop
d5: 90 nop
d6: 90 nop
d7: 90 nop
d8: 90 nop
d9: 90 nop
da: 90 nop
db: 90 nop
dc: 90 nop
dd: 90 nop
de: 90 nop
df: 90 nop
edit: The problem basically lied in me not doing this on a linux distribution, with all the things I'd need to do to do it in Windows not properly set up, huge thanks to MichaelPetch who explained the problems to me, I've now switched to a linux VM and after slightly correcting the code, it works (as the comments pointed out my offset was weird, I used that offset as it worked in the broken setup I had, but normally it shouldn't).