Various tutorials:
http://www.programmingtutorials.com/tutorial.asp?id=Asm
There actually isn't much to assembly. The trouble comes from interfacing with the operating system. Also, different assemblers have idiosyncratic add-ons that are meant to help the experienced programmer, and these can cause considerable confusion.
The best teacher, IMO, is other people's code and Intel's own documentation. Unfortunately, the best little programming examples in assembly were written a long time ago in assembers that aren't as popular anymore. Today, NASM is the drug of choice. In the past, professionals used MASM and hackers used TASM. Even so, if you start with NASM examples, then branch into cool little TASM programs on simtel.net, you'll learn a lot.
If you have an Intel machine, you'll want this:
http://www.baldwin.cx/386htm/toc.htm
To get you started with a NASM example, here is an early version of something I wrote for an assembly tutorial a while ago (sorry, I couldn't find the final, neater version). Get NASM; have the docs close by; Ralf Brown's interrupt list (
www.ctyme.com/intr/int.htm); the Instruction set above; and go crazy. You won't understand the algorithm, but you will like the result. This assumes you are generating a COM file in some kind of Microsoft environment.
org 0x0100
???mov???ax,13h
???int???10h
???
???mov dx, 03d4h ;this chunk modifies the VGA to be 320x100???
???mov al, 09h
???out dx, al
???inc dx ???
???mov al, 03h
???out dx,al
???
???
???mov ax, 0a000h
???mov es, ax
???
???mov al, 63
???mov ch,3
???mov di, 64*3
???rep stosb
???mov???si,2+63*3
???xor???ax,ax
???
???call???PaletteGenProc
???inc???bx
???call???PaletteGenProc
???mov???si,1+63*3
???call???PaletteGenProc
???
???xor???si,si
???call???PaletteGenProc
???mov???ax,1012h ;and set it
???mov???cl,255
???xor???dx,dx
???int???10h???
Render:???xor ???di, di
???mov???si,buffer
???mov???cx,16000
???rep???movsw??????;copy the buffer to screen
???call ???FireProc
???mov???ah,1??????;check if a key is pressed
???int???16h
???jz???Render??????;if not, jump to Render
???
???mov???ax,3h
???int???10h??????;set textmode 80*25
???ret?????????; short way to return to DOS from a COM
???
PaletteGenProc
???mov???cl,64
???xor???ax,ax
Paloop:???mov???[es:si],al
???add???al,bl
???add???si,3
???loop???Paloop
???ret
FireProc
???mov???cx,320
???mov???di, buffer+34560-320???;beginning of the bottom line
???mov???ax,[seed]
???mov???bl,ah
@@1:???mul???si?????????;generate "random" number
???inc???ax
???cmp???al,32??????;also try 64
???jnb???@@2
???mov???bl,ah
@@2:???mov???[di],bl
???mov???[di-320],bl
???inc???di
???loop???@@1
???mov???[seed],ax
???mov???di,buffer
???xor???ax,ax
???xor???dx,dx
???mov???cx,34560
;in this loop, the colors are smoothed and moved one pixel up
@@3:???mov???al,[di+640]
???mov???dl,[di]
???add???ax,dx
???mov???dl,[di+1+320]
???add???ax,dx
???mov???dl,[di-1+320]
???add???ax,dx
???shr???ax,2
???jz???@@4
???dec???ax???;the flames must be darker at the top
@@4:???mov???[di],al
???inc???di
???loop???@@3
ret
??????
seed???dw???5??????;seed for the random-generator
buffer:???times 34560 db 0