------------------------------------------------------------------------------
MC logo
Max of Three
[^] 386 Assembler Language
------------------------------------------------------------------------------
[Chapter 1: Introduction] [Chapter 2: Data Representation] [Chapter 3: Boolean Algebra and Digital Logic] [Chapter 4: MARIE: A Very Simple Architecture] [386 Assembler Language] [Chapter 5: Real-World Architectures] [Chapter 6: Memory Systems] [Chapter 7: I/O Systems] [Chapter 9: Alternative Architecture] [Chapter 11: Performance Measurement]
[Hello, World!] [Counter] [Max of Three]
maxer.s
;;; This program prompts for and reads three integers, then prints the
;;; maximim of the three.  Demonstrates calling and stack manipulation
;;; including calling two internal functions.
        global  main
        extern  printf
        extern  scanf

        section .text

        ;; Read the first two inputs, and push them on the stack.
        ;; Note: We use a dirty trick (three times!) of moving a value to
        ;; the stacktop instead of discarding the top, then pushing a value.
main:   push    p1
        call    req
        mov     [esp],eax       ; Replace prompt on stacktop with result

        push    p2
        call    req
        mov     [esp],eax       ; Now, the first two nums are on the stack.

        ;; Find the larger of the two inputs.  Parms already on the stack
        call    max
        add     esp,8           ; Lose the two args
        push    eax             ; Put the max there.

        ;; Ask the other input and get it on the stack
        push    p3
        call    req
        mov     [esp],eax       ; Now the previous max and new number on top.

        ;; Get the max (in EAX)
        call    max
        add     esp,8

        ;;  Print the result
        push    eax
        push    mfmt
        call    printf
        add     esp,8

        ;; All done
        ret

        section .data
        ;; Three prompts, and the max message.
p1:     db      'Please enter the first integer',0
p2:     db      'How about another one',0
p3:     db      'And one more, just for fun',0
mfmt:   db      'The largest one is %d.',10,0

        section .text
; Return the maximum of two integers.
max:    mov     eax, [esp+4]    ; Load first arg
        cmp     eax, [esp+8]    ; Compare to the second argument
        jg      noch            ; If it's already the max don't change it.
        mov     eax, [esp+8]    ; Change it.

; Wrap it up.  Leaves the max in eax, which is the return.
noch:   ret

; Request and return an integer.  Argument is a prompt string.
req:    push    ebp             ; Set up the frame ptr
        mov     ebp, esp

        sub     esp, 4          ; Make some room for a temp variable

        ;; Make the prompt.
        push    dword [ebp+8]   ; Push argument (string) as arg to printf.
        push    strfmt          ; Push the format as arg to printf.
        call    printf
        add     esp,8           ; Remove args from stack.

        ;; Read the value
        lea     eax,[ebp-4]     ; Address of the temp variable on the stack.
        push    eax             ; Put it on the stack
        push    rdfmt           ; Reading format.
        call    scanf
        add     esp,8           ; Remove from stack.

        ;; Make the read value the return value
        mov     eax,[ebp-4]

        ;; Clean up
        add     esp, 4
        mov     esp, ebp
        pop     ebp
        ret

        section .data
strfmt: db      '%s: ',0        ; Printf format for printing the promt.
rdfmt:  db      '%d',0          ; Scanf format for reading an integer value.