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