Mini Operating System in Assembly Assignment 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 boot sector. 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