I used to, but don't need to any more thank God!
Assembly language is VERY low level language, and involves you writing nmenonics that are translated direct into binary code ("assembled" - hence the name) that the processor can handle.
Biggest bugbear is that there is no generic 'assembly language', you have to learn the commands available on each specific processor and how its individual registers and accumulator etc are manpulated - e.g. (using once popular 8 bit processors as an example) the Z80 (Spectrum etc) has a completely different set of operations and completely different register architecture to the 6502/6510 (BBC/Commodore). You have complete control over the processor/ memory with assembly, but you have to do EVERYTHING yourself, right down to deciding where and how variables are stored and making sure you don't break any rules and (classic error) keep a good track on what you put on "the stack".
a chunk of Z80 assembler might look like this:-
wait: ld hl,ticks
ld a,(hl)
add a,b
wt1: cp (hl)
jp m,wt2
call foo
jr wt1
wt2: ret
This is basically a for-next loop - the reason it's here is that if you wrote the same loop in 6502 it would look entirely different because the 6502 has entirely different register structure.
Line 2 is an instruction to load the accumulator (a register) with the value held in the HL register. in 6502 you can't do that, there is no HL register - instead you have to load either the X or Y registers with the value from the memory location and then transfer this to the accumulator so line 2 is now:
TXA
See what I mean by having to know the individual processor architecture?
With assembler you tend to get no "safety net", you can very easily crash your computer writing assembly language programs - trust me on this as I've done it many, many times
The upside of assembly language is that (used expertly) it makes for blindingly fast, compact code, the downside is that it's a complete PITA to use and very very slow to write/debug.
These days, most people use higher level tools like C/C++ which gives a much more friendly (yes - really it is!) way to generate code that is compiled to executable form. Essentially you can think of it as C++ being initially processed to assembly language which is itself then compiled to an executable. The advantage is that C/C++ is (Microsoft idiocy aside) if not quite the same on all platforms, at least still recognisably the same language.
Assembly language is still useful - there is no better way to write control code for a specific device and things like graphics routines for specific video cards benefit from the added speed it brings, but for many other applications it really is re-inventing the wheel for what is often only a modest improvement over C++ generated code.
Al (a.k.a. MaDbRiT)