Mini Operating System in Assembly

Mini Operating System in Assembly Homework Sample

You are to write a simple OS (not powerful enough to run any software), but it should report the total system memory, and then the types of memory, for each range. You need to create a virtual disk image with the boot image. The memory types for each range are USABLE RAM, RESERVED, ACPI RECLAIMABLE MEMORY, ACPI NVS MEMORY, or BAD MEMORY. You should use the GNU assembler, gas. The code should fit into the 512 byte bootsector. For more assembly language programming assignments contact us for a competitive quote.

Solution:

memos-1.s

.globl _start

.code16

.equ mmap_ent,0x8000

_start:
movw $0x9000, %ax
movw %ax, %ss
xorw %sp, %sp

# set video mode
movw $0x0003, %ax
int $0x10

movw $0x7C0, %ax # set data segment to address $0x7C0 used by BIOS
movw %ax, %ds # to load our boot sector
movw %ax, %es # set es to same segment

movw $Message1, %ax
call printStr

do_e820: # get memory map using e820
movw $0x8004, %di
xorl %ebx, %ebx
xorw %bp, %bp
movl $0x0534D4150,%edx
movl $0xe820, %eax
movl $1, 20(%di)
movl $24, %ecx
int $0x15
jc .failed

movl $0x0534D4150, %edx
cmpl %edx, %eax
jne .failed
testl %ebx, %ebx
je .failed
jmp .jmpin
.e820lp:
movl $0xe820, %eax
movl $1, 20(%di)
mov $24, %ecx
int $0x15
jc .e820f
movl $0x0534D4150, %edx
.jmpin:
jcxz .skipent
cmpb $20, %cl
jbe .notext
testb $1, 20(%di)
je .skipent
.notext:
movl 8(%di), %ecx
orl 12(%di), %ecx
jz .skipent
incw %bp
add $24, %di
.skipent:
testl %ebx, %ebx
jne .e820lp
.e820f:
mov %bp, (mmap_ent)
.failed:

# get available memory
movw (mmap_ent), %cx # get number of entries
movw $0x8004, %si
xorl %eax, %eax
getMem:
cmpl $1, 16(%si) # consider only usable memory
jne 1f
addl 8(%si), %eax # increment count
1: addw $24, %si # advance to next entry
loop getMem

shr $20,%eax # convert to MB

call printNum

movw $Message2, %ax
call printStr

# print memory ranges
movw (mmap_ent), %cx
movw $0x8004, %si
printMem:
pushw %cx
movw $RangeMsg1, %ax
call printStr

movl (%si), %eax
movl %eax, %edi
call printHex

movw $RangeMsg2, %ax
call printStr

movl 8(%si), %eax
subl $1,%eax
addl %edi, %eax
call printHex

movw $RangeMsg3, %ax
call printStr

movl 16(%si),%eax
call printNum

movw $RangeMsg4, %ax
call printStr

addw $24, %si

popw %cx
loop printMem

1: jmp 1b

# print a string on the screen
# on entry: ax=string to print
#
printStr:
pushw %si
movw %ax, %si
1: lodsb
cmpb $0, %al
je 2f
movb $0x0E, %ah
int $0x10
jmp 1b
2: popw %si
ret

# print number on the screen
# on entry: eax=number to print
#
printNum:
movl $10, %ebx
pushl %ebx
1: xorl %edx, %edx
div %ebx
addl $0x30, %edx
pushl %edx
testl %eax, %eax
jne 1b
2: popl %eax
cmp $10, %eax
je 3f
movb $0x0E, %ah
int $0x10
jmp 2b
3: ret

# print a number on the screen as a 32bit hexadecimal
# on entry: ax=number to print
#
printHex:
movl $0, %ebx
pushl %ebx
movl $8, %ecx
1: movl %eax, %edx
andl $0xF, %edx
shr $0x4, %eax
cmp $10, %edx
jge hex
addl $0x30, %edx
jmp save
hex:
addl $0x37, %edx
save:
pushl %edx
loop 1b
2: popl %eax
cmp $0, %eax
je 3f
movb $0x0E, %ah
int $0x10
jmp 2b
3: ret

Message1: .asciz “MemOS: Welcome ***System Memory is: ”
Message2: .asciz “MB\r\n”
RangeMsg1: .asciz “Address range [”
RangeMsg2: .asciz “:”
RangeMsg3: .asciz “] status: ”
RangeMsg4: .asciz “\r\n”

# This is going to be in our MBR, so we need a valid signature
.org 0x1FE

.byte 0x55
.byte 0xAA

# To test:
# as –32 memos-1.s -o memos-1.o
# ld -T memos-1.ld memos-1.o -o memos-1
# dd bs=1 if=memos-1 of=memos-1_test skip=4096 count=512
# qemu-system-i386 -hda memos-1_test

memos-2.s

.globl _start

.equ STACKSIZE,0x4000
.equ MAPSIZE,0x200
.equ DISPLAY,0xB8000
.equ COLS, 80
.equ ROWS, 25
.data

Message1: .asciz “MemOS: Welcome *** System Memory is: ”
Message2: .asciz “MB\n”
RangeMsg1: .asciz “Address range [”
RangeMsg2: .asciz “:”
RangeMsg3: .asciz “] status: ”
RangeMsg4: .asciz “\n”

type1: .asciz “USABLE RAM”
type2: .asciz “RESERVED”
type3: .asciz “ACPI RECLAIMABLE MEMORY”
type4: .asciz “ACPI NVS MEMORY”
type5: .asciz “BAD MEMORY”
strtab: .long 0, type1, type2, type3, type4, type5

x: .long 0
y: .long 0

map_len: .long 0
map: .long 0
memsize: .long 0

.bss
stack: .skip STACKSIZE

.text
_start:
jmp real_start

# Multiboot header — Safe to place this header in 1st page of memory for GRUB
.align 4
.long 0x1BADB002 # Multiboot magic number
.long 0x00000003 # Align modules to 4KB, req. mem size
# See ‘info multiboot’ for further info
.long 0xE4524FFB # Checksum

real_start:
movl $map_len, %edi
movl 44(%ebx), %eax
movl %eax, (%edi)

movl 48(%ebx), %eax
addl %eax, (%edi)

movl $map, %edi
movl %eax, (%edi)

# get available memory
movl $memsize, %edi
movl 4(%ebx), %eax
addl 8(%ebx), %eax
movl %eax, (%edi)

call clearScr

movl $Message1, %eax
call printStr

movl $memsize, %esi
movl (%esi), %eax
shr $10,%eax # convert to MB

call printNum

movl $Message2, %eax
call printStr

# print memory ranges
movl $map_len, %eax
movl (%eax), %ebp

movl $map, %eax
movl (%eax), %esi
printMem:
movl $RangeMsg1, %eax
call printStr

movl 4(%esi), %eax
movl %eax, %edi
call printHex

movl $RangeMsg2, %eax
call printStr

movl 12(%esi), %eax
subl $1,%eax
addl %edi, %eax
call printHex

movl $RangeMsg3, %eax
call printStr

movl 20(%esi),%eax
shll $2, %eax
addl $strtab, %eax
movl (%eax), %eax
call printStr

movl $RangeMsg4, %eax
call printStr
next:
addl 0(%esi), %esi
addl $4, %esi
cmp %ebp, %esi
jl printMem

1: jmp 1b

# print a character on the screen
# on entry: eax=character to print
#
putChar:
pushl %esi
pushl %edi
movl $x, %esi
cmpb $0xa, %al
jne 1f
movl $0,(%esi)
incl 4(%esi)
jmp 2f
1: movl $0x0700, %ecx
movb %al, %cl
movl 4(%esi), %eax
movl $COLS, %ebx
mul %ebx
movl 0(%esi), %edi
addl %eax, %edi
shl $1, %edi
addl $DISPLAY, %edi
movw %cx, (%edi)
incl (%esi)
cmp $COLS,(%esi)
jl 2f
movl $0,(%esi)
incl 4(%esi)
2:
popl %edi
popl %esi
ret

# clear the whole screen
clearScr:
movl $COLS*ROWS, %ecx
movw $0x20, %ax
movl $DISPLAY, %edi
rep stosw
ret

# print a string on the screen
# on entry: eax=string to print
#
printStr:
pushl %esi
movl %eax, %esi
1: lodsb
cmpb $0, %al
je 2f
call putChar
jmp 1b
2: popl %esi
ret

# print number on the screen
# on entry: eax=number to print
#
printNum:
movl $10, %ebx
pushl %ebx
1: xorl %edx, %edx
div %ebx
addl $0x30, %edx
pushl %edx
testl %eax, %eax
jne 1b
2: popl %eax
cmp $10, %eax
je 3f
call putChar
jmp 2b
3: ret

# print a number on the screen as a 32bit hexadecimal
# on entry: ax=number to print
#
printHex:
movl $0, %ebx
pushl %ebx
movl $8, %ecx
1: movl %eax, %edx
andl $0xF, %edx
shr $0x4, %eax
cmp $10, %edx
jge hex
addl $0x30, %edx
jmp save
hex:
addl $0x37, %edx
save:
pushl %edx
loop 1b
2: popl %eax
cmp $0, %eax
je 3f
call putChar
jmp 2b
3: ret

# To test:
# as –32 memos-2.s -o memos-2.o
# ld -T memos-2.ld memos-2.o -o memos-2
# mount disk.img /mnt/C -text2 -o loop,offset=32256
# cp memos-2 /mnt/C/boot/
# umount /mnt/C
# qemu-system-i386 -hda disk.img