Exercises 14.7 Programming 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.
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
bl readLn
add r0, fp, inputString @ user input
bl uDecToInt @ convert it
add r1, r0, 1 @ increment user's number
add r0, fp, outputString
bl uIntToDec
add r0, fp, outputString
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
promptAddr:
.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.
@ 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.
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.
@ 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
promptAddr:
.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
bl readLn
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
