## Exercises14.7Programming Exercises

###### 1.

Write a program in assembly language that asks the user to enter an unsigned integer, adds $1$ to the number, and displays the result.

Solution

The writeStr, readLn, newLine, uDecToInt, and uIntToDec functions have been provided earlier in the book. Here is the main function to solve this problem.

@ incrementDec.s
@ Prompts user for unsigned decimal number and adds 1 to it.
@ 2017-09-29: Bob Plantz

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

@ Constants for assembler
.equ    maxChars,11     @ max input chars
.equ    inputString,-16 @ for input string
.equ    outputString,-28 @ for output string
.equ    locals,32       @ space for local vars

@ Constant program data
.section .rodata
.align  2
prompt:
.asciz        "Enter an unsigned number up to 4294967294: "

@ 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 local vars

ldr     r0, promptAddr  @ prompt user
bl      writeStr

add     r0, fp, inputString  @ place for user input
mov     r1, maxChars    @ limit input size

add     r0, fp, inputString  @ user input
bl      uDecToInt       @ convert it

add     r1, r0, 1       @ increment user's number
bl      uIntToDec

bl      writeStr
bl      newLine

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

.word    prompt

###### 2.

Modify the uIntToDec function (Listing 14.6.1) that you used in Exercise 14.7.1 to use the mls instruction for computing the remainder.

Solution
@ uIntToDecMls.s
@ Converts an int to the corresponding unsigned
@ decimal text string.
@ Calling sequence:
@       r0 <- address of place to store string
@       r1 <- int to convert
@       bl uIntToDec
@ 2017-09-29: Bob Plantz
@ 2017-09-30: Use mls for remainder comp - Bob Plantz

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

@ Constant for assembler
.equ    tempString,-40  @ for temp string
.equ    locals,16       @ space for local vars
.equ    zero,0x30       @ ascii 0
.equ    NUL,0

@ The program
.text
.align  2
.global uIntToDec
.type   uIntToDec, %function
uIntToDec:
sub     sp, sp, 24      @ space for saving regs
str     r4, [sp, 0]     @ save r4
str     r5, [sp, 4]     @      r5
str     r6, [sp, 8]     @      r6
str     r7, [sp, 12]    @      r7
str     fp, [sp, 16]    @      fp
str     lr, [sp, 20]    @      lr
add     fp, sp, 20      @ set our frame pointer
sub     sp, sp, locals @ for local vars

mov     r4, r0          @ caller's string pointer
add     r5, fp, tempString @ temp string
mov     r7, 10          @ decimal constant

mov     r0, NUL         @ end of C string
strb    r0, [r5]
add     r5, r5, 1       @ move to char storage

mov     r0, zero        @ assume the int is 0
strb    r0, [r5]
movs    r6, r1          @ int to convert
beq     copyLoop        @ zero is special case
convertLoop:
cmp     r6, 0           @ end of int?
beq     copy            @ yes, copy for caller
udiv    r0, r6, r7      @ no, div to get quotient
mls     r2, r0, r7, r6  @ the mod (remainder)
mov     r6, r0          @ the quotient
orr     r2, r2, zero    @ convert to numeral
strb    r2, [r5]
add     r5, r5, 1       @ next char position
b       convertLoop
copy:
sub     r5, r5, 1       @ last char stored locally
copyLoop:
ldrb    r0, [r5]        @ get local char
strb    r0, [r4]        @ store the char for caller
cmp     r0, NUL         @ end of local string?
beq     allDone         @ yes, we're done
add     r4, r4, 1       @ no, next caller location
sub     r5, r5, 1       @ next local char
b       copyLoop

allDone:
strb    r0, [r4]        @ end C string
add     sp, sp, locals  @ deallocate local var
ldr     r4, [sp, 0]     @ restore r4
ldr     r5, [sp, 4]     @      r5
ldr     r6, [sp, 8]     @      r6
ldr     r7, [sp, 12]    @      r7
ldr     fp, [sp, 16]    @      fp
ldr     lr, [sp, 20]    @      lr
add     sp, sp, 24      @      sp
bx      lr              @ return

###### 3.

Write a program in assembly language that asks the user to enter a signed integer, adds $1$ to the number, and displays the result.

Hint

This would be a good point to write two functions that will also be useful in subsequent chapters. One, getDecInt will read a signed decimal integer from the keyboard and convert it into int format. The other, putDecInt will convert an int into the signed decimal text string that represents it and write it on the screen. An important software engineering guideline is to reuse code, so you should use your readLn, writeStr, uDecToInt, and uIntToDec functions to implement getDecInt and putDecInt.

Solution
@ incrementSigned.s
@ Prompts user for signed decimal number and adds 1 to it.
@ 2017-09-29: Bob Plantz

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

@ Constant program data
.section .rodata
.align  2
prompt:
.asciz        "Enter a signed integer between -2147483648 and +2147483646: "

@ 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

ldr     r0, promptAddr  @ prompt user
bl      writeStr

bl      getDecInt       @ convert it

add     r0, r0, 1       @ increment user's number
bl      putDecInt       @ print result
bl      newLine

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

.word    prompt

@ getDecInt.s
@ Gets signed decimal integer from keyboard.
@ Calling sequence:
@       bl getDecInt
@ returns equivalent int
@ 2017-09-29: Bob Plantz

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

@ Constants for assembler
.equ    maxChars,12     @ max input chars
.equ    inputString,-20 @ for input string
.equ    locals,8        @ space for local vars

@ Useful source code constants
.equ    POS,0
.equ    NEG,1

@ The program
.text
.align  2
.global getDecInt
.type   getDecInt, %function
getDecInt:
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
sub     sp, sp, locals  @ for the string

add     r0, fp, inputString  @ place to store input
mov     r1, maxChars    @ limit input length

add     r0, fp, inputString  @ input string
mov     r4, POS         @ assume postive int

ldrb    r1, [r0]        @ get char
cmp     r1, '-          @ minus sign?
bne     checkPlus       @ no, check for plus sign
mov     r4, NEG         @ yes, flag as neg
add     r0, r0, 1       @ go to the number
b       convert         @ and convert it
checkPlus:
cmp     r1, '+          @ plus sign?
bne     convert         @ no, we're at the number
add     r0, r0, 1       @ go to the number
convert:
bl      uDecToInt

cmp     r4, POS         @ positive int?
beq     allDone         @ yes, we're done
mvn     r0, r0          @ no, complement it
add     r0, r0, 1       @ and finish negate
allDone:
add     sp, sp, locals  @ deallocate local var
ldr     r4, [sp, 4]     @ restore r4
ldr     fp, [sp, 8]     @         fp
ldr     lr, [sp, 12]    @         lr
add     sp, sp, 16      @         sp
bx      lr              @ return

@ putDecInt.s
@ Converts an int to the corresponding signed
@ decimal text string.
@ Calling sequence:
@       r0 <- int to print
@       bl putDecInt
@ 2017-09-29: Bob Plantz

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

@ Constants for assembler
.equ    decString,-20   @ for  string
.equ    locals,8        @ space for local varsbr

@ Useful source code constants
.equ    POS,0
.equ    NEGBIT,0x80000000

@ The program
.text
.align  2
.global putDecInt
.type   putDecInt, %function
putDecInt:
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
sub     sp, sp, locals  @ space for the string

add     r4, fp, decString  @ place to store string
mov     r1, '+          @ assume positive
strb    r1, [r4]
tst     r0, NEGBIT      @ negative int?
beq     positive        @ no, go on
mov     r1, '-          @ yes, need to negate
strb    r1, [r4]
mvn     r0, r0          @ complement
add     r0, r0, 1       @ two's complement
positive:
mov     r1, r0          @ int to convert
add     r0, r4, 1       @ skip over sign char
bl      uIntToDec

add     r0, fp, decString  @ string to write
bl      writeStr

add     sp, sp, locals  @ deallocate local var
ldr     r4, [sp, 4]     @ restore r4
ldr     fp, [sp, 8]     @         fp
ldr     lr, [sp, 12]    @         lr
add     sp, sp, 16      @         sp
bx      lr              @ return