Author Topic: Want to learn assembly programming  (Read 4984 times)

lordbyronmtg

  • Guest
Want to learn assembly programming
« on: March 18, 2014, 07:55:36 AM »
Hello coders,
I have been programming for over 20 years, but only in high-level languages.  I started with MS-DOS Basic, Turbo-Pascal, then moved to COBOL.  I did COBOL for over 10 years professionally.  I had a mainframe assembler course at DeVry, and even though I know what most of the mneumonics do, I don't understand the low-level stuff well enough to write even a simple program and make it work.  What I need is a recomendation for a book that I could use to learn PC assembler.  I hope someone out there can help. I found an example program called ALARM.ASM in some Microsoft documentation from an older version of their MASM.  I entered it and when I tried using ml.exe to assemble it, I got 8 errors.  I don't know if it's just because the example is from an older version and the assembler I used was version 12.  Any help I can get would be GREATLY appreciated.
Thank you for your time.
lordbyronmtg :t

jj2007

  • Member
  • *****
  • Posts: 13946
  • Assembly is fun ;-)
    • MasmBasic
Re: Want to learn assembly programming
« Reply #1 on: March 18, 2014, 08:29:30 AM »
Hello LB,

First things first: Welcome to the Forum :icon14:

Judging from this hello world program, COBOL is a lot more complicated than assembler:

include \masm32\include\masm32rt.inc
.code
start:   print "Hello World", 13, 10
   exit
end start

To get you started, have a thorough look at Tips, Tricks and Traps. It has also a condensed section on what to read.

ALARM.ASM? Sounds like good ol' DOS assembly. Forget it quickly ;-)

See you soon here with questions :t

MichaelW

  • Global Moderator
  • Member
  • *****
  • Posts: 1196
Re: Want to learn assembly programming
« Reply #2 on: March 18, 2014, 11:51:24 AM »
Judging from the use of the HL syntax and the reference to PWB, the ALARM.ASM that I have must have been included with MASM 6.0.
Code: [Select]
;* ALARM.ASM - A simple memory-resident program that beeps the speaker
;* at a prearranged time.  Can be loaded more than once for multiple
;* alarm settings.  During installation, ALARM establishes a handler
;* for the timer interrupt (interrupt 08).  It then terminates through
;* the Terminate-and-Stay-Resident function (function 31h).  After the
;* alarm sounds, the resident portion of the program retires by setting
;* a flag that prevents further processing in the handler.
;*
;* NOTE: You must assemble this program as a .COM file, either as a PWB
;*       build option or with the ML /AT option.

        .MODEL tiny, pascal, os_dos
        .STACK

        .CODE

        ORG     5Dh                     ; Location of time argument in PSP,
CountDown       LABEL   WORD            ;   converted to number of 5-second
                                        ;   intervals to elapse
        .STARTUP
        jmp     Install                 ; Jump over data and resident code

; Data must be in code segment so it won't be thrown away with Install code.

OldTimer        DWORD   ?               ; Address of original timer routine
tick_91         BYTE    91              ; Counts 91 clock ticks (5 seconds)
TimerActiveFlag BYTE    0               ; Active flag for timer handler

;* NewTimer - Handler routine for timer interrupt (interrupt 08).
;* Decrements CountDown every 5 seconds.  No other action is taken
;* until CountDown reaches 0, at which time the speaker sounds.

NewTimer PROC   FAR

        .IF     cs:TimerActiveFlag != 0 ; If timer busy or retired,
        jmp     cs:OldTimer             ;   jump to original timer routine
        .ENDIF
        inc     cs:TimerActiveFlag      ; Set active flag
        pushf                           ; Simulate interrupt by pushing flags,
        call    cs:OldTimer             ;   then far-calling original routine
        sti                             ; Enable interrupts
        push    ds                      ; Preserve DS register
        push    cs                      ; Point DS to current segment for
        pop     ds                      ;   further memory access
        dec     tick_91                 ; Count down for 91 ticks
        .IF     zero?                   ; If 91 ticks have elapsed,
        mov     tick_91, 91             ;   reset secondary counter and
        dec     CountDown               ;   subtract one 5-second interval
        .IF     zero?                   ; If CountDown drained,
        call    Sound                   ;   sound speaker
        inc     TimerActiveFlag         ; Alarm has sounded, set flag
        .ENDIF
        .ENDIF

        dec     TimerActiveFlag         ; Decrement active flag
        pop     ds                      ; Recover DS
        iret                            ; Return from interrupt handler

NewTimer ENDP


;* Sound - Sounds speaker with the following tone and duration:

BEEP_TONE       EQU     440             ; Beep tone in hertz
BEEP_DURATION   EQU     6               ; Number of clocks during beep,
                                        ;   where 18 clocks = approx 1 second

Sound   PROC    USES ax bx cx dx es     ; Save registers used in this routine
        mov     al, 0B6h                ; Initialize channel 2 of
        out     43h, al                 ;   timer chip
        mov     dx, 12h                 ; Divide 1,193,180 hertz
        mov     ax, 34DCh               ;   (clock frequency) by
        mov     bx, BEEP_TONE           ;   desired frequency
        div     bx                      ; Result is timer clock count
        out     42h, al                 ; Low byte of count to timer
        mov     al, ah
        out     42h, al                 ; High byte of count to timer
        in      al, 61h                 ; Read value from port 61h
        or      al, 3                   ; Set first two bits
        out     61h, al                 ; Turn speaker on

; Pause for specified number of clock ticks

        mov     dx, BEEP_DURATION       ; Beep duration in clock ticks
        sub     cx, cx                  ; CX:DX = tick count for pause
        mov     es, cx                  ; Point ES to low memory data
        add     dx, es:[46Ch]           ; Add current tick count to CX:DX
        adc     cx, es:[46Eh]           ; Result is target count in CX:DX
        .REPEAT
        mov     bx, es:[46Ch]           ; Now repeatedly poll clock
        mov     ax, es:[46Eh]           ;   count until the target
        sub     bx, dx                  ;   time is reached
        sbb     ax, cx
        .UNTIL  !carry?

        in      al, 61h                 ; When time elapses, get port value
        xor     al, 3                   ; Kill bits 0-1 to turn
        out     61h, al                 ;   speaker off
        ret

Sound   ENDP



;* Install - Converts ASCII argument to valid binary number, replaces
;* NewTimer as the interrupt handler for the timer, then makes program
;* memory resident by exiting through function 31h.
;*
;* This procedure marks the end of the TSR's resident section and the
;* beginning of the installation section.  When ALARM terminates through
;* function 31h, the above code and data remain resident in memory.  The
;* memory occupied by the following code is returned to DOS.


Install PROC

; Time argument is in hhmm military format.  Convert ASCII digits to
; number of minutes since midnight, then convert current time to number
; of minutes since midnight.  Difference is number of minutes to elapse
; until alarm sounds.  Convert to seconds-to-elapse, divide by 5 seconds,
; and store result in word CountDown.

DEFAULT_TIME    EQU     3600            ; Default alarm setting = 1 hour
                                        ;   (in seconds) from present time
        mov     ax, DEFAULT_TIME
        cwd                             ; DX:AX = default time in seconds
        .IF     BYTE PTR CountDown != ' ';If not blank argument,
        xor     CountDown[0], '00'      ;   convert 4 bytes of ASCII
        xor     CountDown[2], '00'      ;   argument to binary
                                       
        mov     al, 10                  ; Multiply 1st hour digit by 10
        mul     BYTE PTR CountDown[0]   ;   and add to 2nd hour digit
        add     al, BYTE PTR CountDown[1]
        mov     bh, al                  ; BH = hour for alarm to go off
        mov     al, 10                  ; Repeat procedure for minutes
        mul     BYTE PTR CountDown[2]   ; Multiply 1st minute digit by 10
        add     al, BYTE PTR CountDown[3] ;   and add to 2nd minute digit
        mov     bl, al                  ; BL = minute for alarm to go off
        mov     ah, 2Ch                 ; Request function 2Ch
        int     21h                     ; Get Time (CX = current hour/min)
        mov     dl, dh
        sub     dh, dh
        push    dx                      ; Save DX = current seconds

        mov     al, 60                  ; Multiply current hour by 60
        mul     ch                      ;   to convert to minutes
        sub     ch, ch
        add     cx, ax                  ; Add current minutes to result
                                        ; CX = minutes since midnight
        mov     al, 60                  ; Multiply alarm hour by 60
        mul     bh                      ;   to convert to minutes
        sub     bh, bh
        add     ax, bx                  ; AX = number of minutes since
                                        ;   midnight for alarm setting
        sub     ax, cx                  ; AX = time in minutes to elapse
                                        ;   before alarm sounds
        .IF     carry?                  ; If alarm time is tomorrow,
        add     ax, 24 * 60             ;   add minutes in a day
        .ENDIF

        mov     bx, 60
        mul     bx                      ; DX:AX = minutes-to-elapse-times-60
        pop     bx                      ; Recover current seconds
        sub     ax, bx                  ; DX:AX = seconds to elapse before
        sbb     dx, 0                   ;   alarm activates
        .IF     carry?                  ; If negative,
        mov     ax, 5                   ;   assume 5 seconds
        cwd
        .ENDIF
        .ENDIF

        mov     bx, 5                   ; Divide result by 5 seconds
        div     bx                      ; AX = number of 5-second intervals
        mov     CountDown, ax           ;   to elapse before alarm sounds

        mov     ax, 3508h               ; Request function 35h
        int     21h                     ; Get vector for timer (interrupt 08)
        mov     WORD PTR OldTimer[0], bx; Store address of original
        mov     WORD PTR OldTimer[2], es;   timer interrupt
        mov     ax, 2508h               ; Request function 25h
        mov     dx, OFFSET NewTimer     ; DS:DX points to new timer handler
        int     21h                     ; Set vector with address of NewTimer

        mov     dx, OFFSET Install      ; DX = bytes in resident section
        mov     cl, 4
        shr     dx, cl                  ; Convert to number of paragraphs
        inc     dx                      ;   plus one
        mov     ax, 3100h               ; Request function 31h, error code=0
        int     21h                     ; Terminate-and-Stay-Resident

Install ENDP

        END

The interrupt handler (NewTimer) is interesting. Whoever coded this apparently knew that the HL syntax used to access memory operands in the handler would not modify registers, and knowledge of this detail could be useful still. It assembles and links for me with no problems, but I did not bother to test it on a DOS system.

Well Microsoft, here’s another nice mess you’ve gotten us into.

Gunther

  • Member
  • *****
  • Posts: 4196
  • Forgive your enemies, but never forget their names
Re: Want to learn assembly programming
« Reply #3 on: March 18, 2014, 09:03:54 PM »
Hi lordbyronmtg,

welcome to the forum. You should download the masm32 package and follow Jochen's advice. Furthermore, there are a lot of working examples inside the masm32 package. Have fun.

Gunther
You have to know the facts before you can distort them.

Vortex

  • Member
  • *****
  • Posts: 2790
Re: Want to learn assembly programming
« Reply #4 on: March 19, 2014, 06:48:37 AM »
Hi lordbyronmtg,

Welcome to the forum.

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 10583
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Want to learn assembly programming
« Reply #5 on: March 20, 2014, 04:56:53 PM »
Byron,

Do a Google search for WINHELP and you should get a direct link to Microsoft for the OS version you are running.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

K_F

  • Member
  • *****
  • Posts: 1770
  • Anybody out there?
Re: Want to learn assembly programming
« Reply #6 on: March 21, 2014, 10:04:23 AM »
Hello.. M'Lord
Here's a Pumpkin link https://en.wikipedia.org/wiki/X86_assembly_language

O'ild look at the Manuals you know.. there at the bottom o'er the page.
The Intel one Ye be panderin fer... nudge nudge

send me a pint
 :eusa_boohoo:
'Sire, Sire!... the peasants are Revolting !!!'
'Yes, they are.. aren't they....'