PDA

View Full Version : Assembly Tutorials



JoshR
06-03-2005, 04:24 PM
Anyone found some great assembly tutorials? I really want to learn assembly, thinking of making my own OS in the future, or building on an existing one so assembly would really help.

Thanks,
Josh

sean
06-03-2005, 04:30 PM
As someone who has worked on his own OS before, I would give you the following little tidbit of information: The only part of an OS that has to be in assembly is the very small boot loader - and unless you want to write your own file system too (quite difficult), there are already boot loaders written for you. I have an example for FAT 12 if you want to take a look at it.

The kernel and everything else could be (and often is) written in C/C++ if you wanted. Granted, you wouldn't be able to use the standard libraries, but it saves you a lot of trouble from assembly. You'd write some simple i/o routines in assembly, make them functions, and you'd be all set.

I was making a server OS, and the reason I stopped is because of the device drivers I would need. It's a fun project and you learn a lot, but just be aware that this is a much bigger project than you may think.

As for a tutorial, I'm afraid I can't suggest one. I've mostly learned from books.

sean
06-03-2005, 04:34 PM
Also - try Google. I know it's directory was a wealth of information for me when I was doing my OS.

^xor
06-03-2005, 06:24 PM
Pretty good free assembly book that focuses on Linux and uses AT&T syntax:
http://savannah.nongnu.org/projects/pgubook/

JoshR
06-03-2005, 09:59 PM
Thanks guys, Ya I know it would be a lot of work, but its such a cool thing to do. And I will learn so much, It would probably take more than a year but I think it would be worth it.

JoshR
06-03-2005, 10:08 PM
Yeah sean could you post your example for FAT 12. I just want to see whats involved, and how its structured. Thanks

Zach L.
06-03-2005, 10:28 PM
Art of Assembly (http://webster.cs.ucr.edu/AoA/index.html) perhaps.

sand_man
06-03-2005, 10:47 PM
I also recommend Art of Assembly. It goes into detail about everything.

Pete
06-04-2005, 02:20 AM
I've worked on OSes (strictly speaking still working on one but other stuff has taken over in importance). But I can recommend quite a few good websites:-

http://www.mega-tokyo.com/forum/index.php?board=1
http://my.execpc.com/~geezer/osd/
http://my.execpc.com/~geezer/os/
http://www.osdever.net/
http://www.osdever.net/cottontail/ - The intel manuals from here are essential (especially volumes 2+3)
http://www.osdev.org/
http://www.mega-tokyo.com/osfaq2/
http://oslib.codymays.net/
http://www.nondot.org/~sabre/os/

And for a bootloader, I would use GRUB, it's easy to setup and allows loading of modules and gives some system information. This helps alot when starting and even once the OS is finished, having it load a few modules helps, as then no drivers have to be physically loaded into the kernel (could still run at ring0 if you wanted monolithic - although no a great idea). You'll probably find that its best off just playing around with code to begin with (especially the OSD kernels above), but before you make a stab at a kernel which'll be any good, you'll really have to plan stuff out

Hope this helps

Pete

sean
06-04-2005, 08:30 AM
Before I post this, I should clarify that this is NOT my work - it was an example given in a tutorial on making operating systems. I'll try and find the site for you, but for now, this is the code:


;************************************************* ************************
;the ultimate boot-strap loader
;to load a file from a DOS FAT12 floppy as the OS
;************************************************* ************************
[BITS 16]
[ORG 0x0000]
jmp START

OEM_ID db "QUASI-OS"
BytesPerSector dw 0x0200
SectorsPerCluster db 0x01
ReservedSectors dw 0x0001
TotalFATs db 0x02
MaxRootEntries dw 0x00E0
TotalSectorsSmall dw 0x0B40
MediaDescriptor db 0xF0
SectorsPerFAT dw 0x0009
SectorsPerTrack dw 0x0012
NumHeads dw 0x0002
HiddenSectors dd 0x00000000
TotalSectorsLarge dd 0x00000000
DriveNumber db 0x00
Flags db 0x00
Signature db 0x29
VolumeID dd 0xFFFFFFFF
VolumeLabel db "QUASI BOOT"
SystemID db "FAT12 "

START:
; code located at 0000:7C00, adjust segment registers
cli
mov ax, 0x07C0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; create stack
mov ax, 0x0000
mov ss, ax
mov sp, 0xFFFF
sti
; post message
mov si, msgLoading
call DisplayMessage
LOAD_ROOT:
; compute size of root directory and store in cx
xor cx, cx
xor dx, dx
mov ax, 0x0020 ; 32 byte directory entry
mul WORD [MaxRootEntries] ; total size of directory
div WORD [BytesPerSector] ; sectors used by directory
xchg ax, cx
; compute location of root directory and store in ax
mov al, BYTE [TotalFATs] ; number of FATs
mul WORD [SectorsPerFAT] ; sectors used by FATs
add ax, WORD [ReservedSectors] ; adjust for bootsector
mov WORD [datasector], ax ; base of root directory
add WORD [datasector], cx
; read root directory into memory (7C00:0200)
mov bx, 0x0200 ; copy root dir above bootcode
call ReadSectors
; browse root directory for binary image
mov cx, WORD [MaxRootEntries] ; load loop counter
mov di, 0x0200 ; locate first root entry
.LOOP:
push cx
mov cx, 0x000B ; eleven character name
mov si, ImageName ; image name to find
push di
rep cmpsb ; test for entry match
pop di
je LOAD_FAT
pop cx
add di, 0x0020 ; queue next directory entry
loop .LOOP
jmp FAILURE
LOAD_FAT:
; save starting cluster of boot image
mov si, msgCRLF
call DisplayMessage
mov dx, WORD [di + 0x001A]
mov WORD [cluster], dx ; files first cluster
; compute size of FAT and store in cx
xor ax, ax
mov al, BYTE [TotalFATs] ; number of FATs
mul WORD [SectorsPerFAT] ; sectors used by FATs
mov cx, ax
; compute location of FAT and store in ax
mov ax, WORD [ReservedSectors] ; adjust for bootsector
; read FAT into memory (7C00:0200)
mov bx, 0x0200 ; copy FAT above bootcode
call ReadSectors
; read image file into memory (0100:0000)
mov si, msgCRLF
call DisplayMessage
mov ax, 0x0100 ; destination of image CS
mov es, ax
mov bx, 0x0000 ; destination for image IP
push bx
LOAD_IMAGE:
mov ax, WORD [cluster] ; cluster to read
pop bx ; buffer to read into
call ClusterLBA ; convert cluster to LBA
xor cx, cx
mov cl, BYTE [SectorsPerCluster] ; sectors to read
call ReadSectors
push bx
; compute next cluster
mov ax, WORD [cluster] ; identify current cluster
mov cx, ax ; copy current cluster
mov dx, ax ; copy current cluster
shr dx, 0x0001 ;
;divide by two
add cx, dx ; sum for (3/2)
mov bx, 0x0200 ; location of FAT in memory
add bx, cx ; index into FAT
mov dx, WORD [bx] ; read two bytes from FAT
test ax, 0x0001
jnz .ODD_CLUSTER
.EVEN_CLUSTER:
and dx, 0000111111111111b ; take low twelve bits
jmp .DONE
.ODD_CLUSTER:
shr dx, 0x0004 ; take high twelve bits
.DONE:
mov WORD [cluster], dx ; store new cluster
cmp dx, 0x0FF0 ; test for end of file
jb LOAD_IMAGE
DONE:
mov si, msgCRLF
call DisplayMessage
push WORD 0x0100
push WORD 0x0000
retf
FAILURE:
mov si, msgFailure
call DisplayMessage
mov ah, 0x00
int 0x16 ; await keypress
int 0x19 ; warm boot computer

;************************************************* ************************
; PROCEDURE DisplayMessage
; display ASCIIZ string at ds:si via BIOS
;************************************************* ************************
DisplayMessage:
lodsb ; load next character
or al, al ; test for NUL character
jz .DONE
mov ah, 0x0E ; BIOS teletype
mov bh, 0x00 ; display page 0
mov bl, 0x07 ; text attribute
int 0x10 ; invoke BIOS
jmp DisplayMessage
.DONE:
ret

;************************************************* ************************
; PROCEDURE ReadSectors
; reads cx sectors from disk starting at ax into
;memory location es:bx
;************************************************* ************************
ReadSectors:
.MAIN
mov di, 0x0005 ; five retries for error
.SECTORLOOP
push ax
push bx
push cx
call LBACHS
mov ah, 0x02 ; BIOS read sector
mov al, 0x01 ; read one sector
mov ch, BYTE [absoluteTrack] ; track
mov cl, BYTE [absoluteSector] ; sector
mov dh, BYTE [absoluteHead] ; head
mov dl, BYTE [DriveNumber] ; drive
int 0x13 ; invoke BIOS
jnc .SUCCESS ; test for read error
xor ax, ax ; BIOS reset disk
int 0x13 ; invoke BIOS
dec di ; decrement error counter
pop cx
pop bx
pop ax
jnz .SECTORLOOP ; attempt to read again
int 0x18
.SUCCESS
mov si, msgProgress
call DisplayMessage
pop cx
pop bx
pop ax
add bx, WORD [BytesPerSector] ; queue next buffer
inc ax ; queue next sector
loop .MAIN ; read next sector
ret

;************************************************* ************************
; PROCEDURE ClusterLBA
; convert FAT cluster into LBA addressing scheme
; LBA = (cluster - 2) * sectors per cluster
;************************************************* ************************
ClusterLBA:
sub ax, 0x0002 ; zero base cluster number
xor cx, cx
mov cl, BYTE [SectorsPerCluster] ; convert byte to word
mul cx
add ax, WORD [datasector] ; base data sector
ret

;************************************************* ************************
; PROCEDURE LBACHS
; convert ax LBA addressing scheme to CHS addressing scheme
; absolute sector = (logical sector / sectors per track) + 1
; absolute head = (logical sector / sectors per track) MOD number of heads
; absolute track = logical sector / (sectors per track * number of heads)
;************************************************* ************************
LBACHS:
xor dx, dx ; prepare dx:ax for operation
div WORD [SectorsPerTrack] ; calculate
inc dl ; adjust for sector 0
mov BYTE [absoluteSector], dl
xor dx, dx ; prepare dx:ax for operation
div WORD [NumHeads] ; calculate
mov BYTE [absoluteHead], dl
mov BYTE [absoluteTrack], al
ret

absoluteSector db 0x00
absoluteHead db 0x00
absoluteTrack db 0x00

datasector dw 0x0000
cluster dw 0x0000
ImageName db "KERNEL BIN"
msgLoading db 0x0D, 0x0A, "Loading Boot Image ", 0x0D, 0x0A, 0x00
msgCRLF db 0x0D, 0x0A, 0x00
msgProgress db ".", 0x00
msgFailure db 0x0D, 0x0A, "ERROR : Press Any Key to Reboot", 0x00

TIMES 510-($-$$) DB 0
DW 0xAA55


Again, I'll try and find the site this came from, as you'd learn a lot about the bootstrap from the rest of the tutorial. I also wrote a very simple ASM kernel that you could build off of - it has the basics of I/O done.

Pete
06-04-2005, 08:58 AM
Erm, that bootsector doesn't put you into protected mode. Although you could do this yourself, it makes it more difficult as very few C compilers will support 16bit mode AND 32bit so you'd have to add a second stage loaded.

The bootsector I use is attached, it performs pretty much everything you could want. But you have to have the 2 files it tries to load on the disk otherwise it'll just hang (no space left for error message code). It'll load a flat binary to 0x100000, enable pmode, load the second file (a config file or whatever you want), get a map of the available memory from the bios (can't use bios functions once you're in pmode) - from a floppy, not tested on any hard drive.

Also another suggestion, don't go in trying to write the OS in C++, cause you have to write a memory manager immediately to cope with the new and delete constructors... (think that's right - I never use C++ myself for anything)

Pete

7smurfs
06-09-2005, 08:18 PM
Can I ask why you can't use the STL in programming the OS?

Stoned_Coder
06-09-2005, 10:21 PM
because STL makes use of new and new relies on an operating system.

okinrus
06-11-2005, 09:56 AM
You could prabably get by creating your own STL allocators. Never tried to do that though.