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
Solution
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.
@ 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
