Skip to main content

Exercises 15.7 Programming Exercise

1.

Write a program in assembly language that performs like the C++ program in Listing 15.6.6. That is, it will allow the user to enter the numerator and denominator of a fraction, add \(1\) to the fraction, and display the result.

Hint

Consider starting with the solution to Exercise 15.5.1 instead of using the compiler-generated assembly language for the C++ program in Listing 15.6.6.

Solution
@ incFraction.s
@ Gets values from user for a fraction, adds 1
@ to the fraction, and then displays the result.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    x,-12           @ x fraction object
        .equ    locals,8        @ space for fraction

@ The program
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        sub     sp, sp, locals  @ for the structs
        
@ construct the fraction
        add     r0, fp, x       @ address of x struct
        bl      fractionConstr

@ get user input
        add     r0, fp, x       @ get user values
        bl      fractionGet

@ add 1
        add     r0, fp, x       @ add 1 to it
        mov     r1, 1 
        bl      fractionAddInt
        
@ display result
        add     r0, fp, x       @ get user values
        bl      fractionDisplay

        mov     r0, 0           @ return 0;
        add     sp, sp, locals  @ deallocate local var
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return
@ fractionObject.s
@ field name definitions; requires 8 bytes
@ 2017-09-29: Bob Plantz

@ fraction object definition
        .equ    num,0    @ numerator
        .equ    den,4    @ denominator
@ fractionConstr.s
@ Construct a fraction object
@ Calling sequence:
@        r0 <- address of fraction variable
@        bl  fractionConstr
@ Returns 0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "fractionObject.s"  @ fraction object defs.
        
@ The code
        .text
        .align  2
        .global fractionConstr
        .type   fractionConstr, %function
fractionConstr:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        
        mov     r1, 1           @ reasonable numerator
        str     r1, [r0, num]
        
        mov     r1, 2           @ reasonable denominator
        str     r1, [r0, den]

        mov     r0, 0           @ return 0;
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return
@ fractionGet.s
@ Gets values for a fraction from keyboard
@ Calling sequence:
@        r0 <- address of the struct
@        bl  getStruct
@ Returns 0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "fractionObject.s"  @ fraction object defs.
        
@ Constant program data
        .section .rodata
        .align  2
numPrompt:
        .asciz        "  Enter numerator: "
denPrompt:
        .asciz        "Enter denominator: "

@ The code
        .text
        .align  2
        .global fractionGet
        .type   fractionGet, %function
fractionGet:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r4, r0          @ pointer to the object
        
        ldr     r0, numPromptAddr
        bl      writeStr        @ ask for numerator
        bl      getDecInt       @ get it
        str     r0, [r4, num]   @ store at this->num
                
        ldr     r0, denPromptAddr
        bl      writeStr        @ ask for denominator
        bl      getDecInt       @ get it
        str     r0, [r4, den]   @ store at this->den

        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return

        .align  2
@ addresses of messages
numPromptAddr:
        .word   numPrompt
denPromptAddr:
        .word   denPrompt
@ fractionAddInt.s
@ Adds an integer to a fraction
@ Assumes (int X den) + num fits into 32 bits.
@ Calling sequence:
@        r0 <- address of the object
@        r1 <- integer to add
@        bl  fractionAddInt
@ Returns 0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "fractionObject.s"  @ fraction object defs.
        
@ The code
        .text
        .align  2
        .global fractionAddInt
        .type   fractionAddInt, %function
fractionAddInt:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r4, r0          @ this pointer
        
        ldr     r0, [r4, den]   @ get denominator
        mul     r2, r1, r0      @ integer X denominator
        ldr     r0, [r4, num]   @ get numerator
        add     r2, r2, r0      @ numerator + (int X den)
        str     r2, [r4, num]   @ save new numerator
        
        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return
@ fractionDisplay.s
@ Displays a fraction struct on screen
@ Calling sequence:
@        r0 <- address of the struct
@        bl  fractionDisplay
@ Returns 0
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .include "fractionObject.s"  @ fraction object defs.
        
@ The code
        .text
        .align  2
        .global fractionDisplay
        .type   fractionDisplay, %function
fractionDisplay:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r4, [sp, 4]     @ save r4
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer
        
        mov     r4, r0          @ this pointer
        
        ldr     r0, [r4, num]   @ display numerator
        bl      putDecInt
        mov     r0, '/          @ slash for fraction
        bl      putChar
        ldr     r0, [r4, den]   @ display denominator
        bl      putDecInt
        bl      newLine

        mov     r0, 0           @ return 0;
        ldr     r4, [sp, 4]     @ restore r4
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return
@ putChar.s
@ Writes a character to the standard output (screen).
@ Calling sequence:
@       r0 <- the character
@       bl    putChar
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Constants for assembler
        .equ    STDOUT,1
        .equ    theChar,-5     @ for  string
        .equ    locals,8       @ space for local var

@ The code
        .text
        .align  2
        .global putChar
        .type   putChar, %function
putChar:
        sub     sp, sp, 8       @ space for fp, lr
        str     fp, [sp, 0]     @ save fp
        str     lr, [sp, 4]     @   and lr
        add     fp, sp, 4       @ set our frame pointer
        sub     sp, sp, locals

        strb    r0, [fp, theChar]  @ write needs address
        mov     r0, STDOUT      @ write to screen
        add     r1, fp, theChar    @ address of theChar
        mov     r2, 1           @ write 1 byte
        bl      write

        mov     r0, 0           @ return 0;
        add     sp, sp, locals  @ deallocate local var
        ldr     fp, [sp, 0]     @ restore caller fp
        ldr     lr, [sp, 4]     @       lr
        add     sp, sp, 8       @   and sp
        bx      lr              @ return