Rot13 in armsim wont read more than one line - arm

I'm writing a rot13 in armsim# everything works besides the fact that it will not read the next line
.equ SWI_Open, 0x66 #open a file
.equ SWI_Close,0x68 #close a file
.equ SWI_PrChr,0x00 # Write an ASCII char to Stdout
.equ SWI_PrStr, 0x69 # Write a null-ending string
.equ SWI_PrInt,0x6b # Write an Integer
.equ SWI_RdInt,0x6c # Read an Integer from a file
.equ SWI_RdStr, 0x6a # Read string from file
.equ Stdout, 1 # Set output target to be Stdout
.equ SWI_Exit, 0x11 # Stop execution
.global _start
.text
_start:
ldr r0,=InFileName # set Name for input file
mov r1,#0 # mode is input
swi SWI_Open # open file for input
ldr r1,=InFileHandle
str r0,[r1]
ldr r7,[r1]
ldr r1,=array
mov r2,#85
swi SWI_RdStr #stores the string into =array
bcs EofReached
mov r5,#0 #r5 is index
loop: #processes a single char then loops back
ldrb r4,[r1,r5] #loads the character value from =array[r5] into r4
cmp r4,#0
BEQ newline
cmp r4,#32
beq skip
cmp r4,#96
bgt lowercase
cmp r4,#91
blt uppercase
uppercase:
cmp r4,#77
ble add
cmp r4,#91
blt sub
lowercase:
cmp r4,#109
ble add
cmp r4,#123
blt sub
add:
add r4,r4,#13
b skip
sub:
sub r4,r4,#26
add r4,r4,#13
skip:
mov r0,r4
swi SWI_PrChr
strb r4,[r1,r5]
add r5,r5,#1
b loop
newline:
bcs EofReached
mov R0,#Stdout # print new line
ldr r1,=NL
swi SWI_PrStr
bal loop
swi SWI_Close
swi SWI_Exit
EofReached:
mov R0, #Stdout # print last message
ldr R1, =EndOfFileMsg
swi SWI_PrStr
Exit:
swi SWI_Exit # stop executing
.data
InFileName: .asciz "lab2.txt"
EndOfFileMsg: .asciz " End of file reached\n"
ColonSpace: .asciz": "
NL: .asciz "\n" # new line
.array: .skip 85
.align
InFileHandle: .word 0
.end
Anyone with knowledge of ARMSIM feel free to help
I'm using this example to help me
http://armsim.cs.uvic.ca/AttachedFiles/ARMSim_UserGuide4Plus.pdf example 11.2 but to no help the program stops reading after one line is finished

Related

I can input number and display what number I input. If i input 10, I need all even numbers between 1-10 added and all odd numbers

.equ READERROR, 0 #Used to check for scanf read error.
.global main # Have to use main because of C library uses.
main:
prompt:
# Ask the user to enter a number.
ldr r0, =strInputPrompt # Put the address of my string into the first parameter
bl printf # Call the C printf to display input prompt.
ldr r0, =numInputPattern # Setup to read in one number.
ldr r1, =intInput # load r1 with the address of where the
# input value will be stored.
bl scanf # scan the keyboard.
cmp r0, #READERROR # Check for a read error.
beq readerror # If there was a read error go handle it.
ldr r1, =intInput # Have to reload r1 because it gets wiped out.
ldr r1, [r1] # Read the contents of intInput and store in r1 so that
# it can be printed
ldr r0, =strOutputNum
bl printf
ldr r0, =strOutputEven
loop:
cmp r1, #101
beq end
cmp r1, #0
bne odd
cmp r1, #1
bne even
odd:
add r1, r1, LSL #1 /* r1 ← r1 + (r1 << 1) */
bl printf
even:
mov r1, r1, ASR #1 /* r1 ← (r1 >> 1) */
b end_loop
end_loop:
add r2, r2, #1 /* r2 ← r2 + 1 */
b loop /* branch to loop */
# Print the input out as a number.
# r1 contains the value input to keyboard.
b myexit # leave the code.
readerror:
# Got a read error from the scanf routine. Clear out the input buffer then
# branch back for the user to enter a value.
# Since an invalid entry was made we now have to clear out the input buffer by
# reading with this format %[^\n] which will read the buffer until the user
# presses the CR.
ldr r0, =strInputPattern
ldr r1, =strInputError # Put address into r1 for read.
bl scanf # scan the keyboard.
Not going to do anything with the input. This just cleans up the input buffer. The input buffer should now be clear so get another input.
b prompt
myexit:
End of my code. Force the exit and return control to OS
mov r7, #0x01 # SVC call to exit
svc 0 # Make the system call.
.data
Declare the strings and data needed
.balign 4
strInputPrompt: .asciz "Input a number between 1 and 100: \n"
.balign 4
strOutputNum: .asciz "You entered: %d \n"
.balign 4
strOutputEven: .asciz "The even numbers from 1 to %d are: \n"
Format pattern for scanf call.
.balign 4
numInputPattern: .asciz "%d" # integer format for read.
.balign 4
strInputPattern: .asciz "%[^\n]" # Used to clear the input buffer for invalid input.
.balign 4
strInputError: .skip 100*4 # User to clear the input buffer for invalid input.
.balign 4
intInput: .word 0 # Location used to store the user input.
.global printf
.global scanf
cannot get even and odd functions to work
The first problem is here:
cmp r1, #0
bne odd
cmp r1, #1
bne even
This actually compares the entire number to 0 or 1, when you only want the rightmost bit. You'll need to do something like this. I'll only list the even case, I think you can figure out the odd. I'm a bit rusty at ARM assembly and haven't tested this but something like it should work:
tst r1,#1 # sets the flags as you did "AND r1,r1,#1" but doesn't change r1
bne odd # now you will jump to label "odd" if r1 is odd, or keep
# going if it's even.
# if it isn't odd, it must be even, so your even code goes here!
push r1-r2 # technically this is a thumb mode only instruction but if your
# assembler allows unified syntax it should get assembled as the
# 32-bit instruction "STMFD sp!,{r1-r2}"
# this saves r1 and r2 on the stack, we get them back with POP.
# C functions assume the stack is aligned to 8 bytes so we have to push
# an even number of registers even though we only needed to push R1.
ldr r0,=strOutputEven # r1 still contains intInput
bl printf # prints "The even numbers from 1 to %d are,"
pop R1-R2 # unified syntax for "LDMFD sp!,{r1-r2}"
# now we'll do the loop:
ldr r0,=numInputPattern
mov r1,#0 # we don't need the input anymore
mov r2,#0 # the sum goes here
loop_even:
add r1,r1,#2
cmp r1,#101
bcc exitLoop # if R1 is greater than or equal to 101, exit.
PUSH R0-R3 # I can't remember what printf alters so better safe than sorry.
bl printf
POP R0-R3
add r2,r2,r1 # add R1 to R2 and store the result in R2.
b loop_even
exitloop:
mov r1,r2 # put the sum into r1 so we can print it
bl printf # print the string
b my_exit # we're done!
odd:
I would recommend reading up on the PUSH and POP instructions and how they work, it's a much more reliable way of temporarily preserving registers than the method you used with ldr r1,[r1]. Don't feel ashamed if you need to print out a reference list of the ARM instructions - I use one all the time.

Segmentation fault if I try to print all the argv arguments with a loop

.global main
.type main%function
# r4 = argc
# r5 = current offset
# r6 = end offset
# r7 = array argv
main:
mov r4,r0
ldr r0,=message
mov r5,#0 // initialize offset
mov r6,#4
mul r6,r4,r6 // calculate end offset
mov r7,r1 // put array argv in r7
loop:
ldr r1,[r7,r5] // load the argv element with offset r5
push {ip,lr} // save lr
bl printf
pop {ip,lr}
add r5,r5,#4 // go to next word
cmp r5,r6
bne loop // if I haven't reached the end offset, it does another cycle
end:
mov r0,#0 // clear exit code
bx lr // returns
message:
.asciz "%s\n"
Output:
$ ./a.out a
./a.out
Segmentation fault
but:
$ ./a.out
./a.out
so apparently the problems comes when I try to access the next element of the array... really don't know why... I'm new with arm and assembly..

Length of string in ARM?

trying to learn some basic ARM and I am trying to figure how to get the length of a string using a while loop. Below is what I am trying to achieve in C and also what I am attempting to do in ARM. My issue comes from the while loop, I am unable to go through the string until I hit the null terminator and to keep track of it with a variable.
char inputString[7];
int lengthOfInput = 0;
while (inputString[lengthOfInput] != '\0')
{
lengthOfInput++;
}
.section .data
#need to include \n if you want to test the output. no idea why
input_prompt : .asciz "string: "
input_spec : .asciz "%[^\n]"
length_spec : .asciz "length: %d\n"
#8 bytes for 7 characters plus \0
input: .space 8
.section .text
.global main
main:
#print prompt
ldr x0, =input_prompt
bl printf
#get input
ldr x0, =input_spec
ldr x1, =input
bl scanf
#call get_length
ldr x9, =input
ldrsw x0, [x9]
bl get_length
#print result from get_length
#to do
#exit
b exit
get_length:
#intializing "i" as 0
add x19, xzr, xzr
get_length_loop:
#address of userString[i]
add x12,x19,x1
#if == 0, go somewhere, maybe get_length should be changed
cbz x12, get_length
add x19,x19, 1
b get_length_loop
#return result
mov x0, x19
ret
exit:
mov x0, 0
mov x8, 93
svc 0
ret

assembly read from file segmentation

.data
pn: .string "input.bin"
string: .string "%f\n"
buf_size = 8
alloc = -(16+buf_size)&-16
dealloc = -alloc
buf_s = 16
.text
.balign 4
.global main
main: stp x29,x30,[sp,alloc]!
mov x29,sp
mov w0,-100
ldr x1,=pn
mov w2,0
mov w3,0
mov x8,56
svc 0
cmp w0,0
mov w19,w0
mov w24,w19
mov x20,0
mov x21,8
b.ge open_ok
open_ok:
mov w0,w19
add x1,x29,x21
mov x2,8
mov x8,63
svc 0
ldr d0,[x1]
ldr x0,=string
bl printf
add x21,x21,8
cmp x20,199
add x20,x20,1
b.lt open_ok
mov w0,w24
mov x8,57
svc 0
mov x1,x0
ldr x0,=string
bl printf
ldp x29,x30,[sp],dealloc
ret
I'm trying to write a program that reads from a file "input.bin" and displays the contents of the file. It reads the file correctly and displays the data the way it is supposed to but right at the end it crashes due to a segmentation fault. Not sure whats going on. Input contains the numbers 0.5 to 100, incremented by 0.5 each time. It prints it out correctly and then crashes right at the end.

ARM Assembly: Array Address not loading properly?

I am working on this homework assignment, and my professor is stumped (as I am too) on why my array address refuses to load into R2. He said my code is correct, but he is absolutely uncertain about why it is behaving this way. It used to load 10 constantly, however, under the branch manageArray:, it should be overwriting the old use of R2. I even tried re-initializing the value, and it never worked.
We have run it under ARMSim, and code it as a .s file under notepad++. If anyone can point out what the potential cause is and why (because I absolutely want to learn from this, not look for answers!), I would be forever in your debt!! We have sat for nearly an hour and sent back so many emails over this, we're just frustrated and lost on where to go. It always loads a value of 10 or 11, but never the array address.
This is my code as of now. Basically, it's meant to check for odds (and terminate if true), else, add all of the array and print that total out. Semi-colons (;) are comments in assembly, which is weird.
.data
oddPrompt: .asciz "This Array is odd: we are terminating this thing.\n\r"
.align
terminatedPrompt: .asciz "YOU HAVE BEEN TERMINATED!\n\r"
.align
totalPrompt: .asciz "Total : \n\r"
.align
arrayLength = 10
;determineArrayOdds = arrayLength
array: .skip arrayLength*4
.text
mov r0,#0
mov r1,#0
mov r2,#arrayLength
mov r3,#0
mov r6,#0 ;element 1
mov r7,#0 ;element 2
mov r8,#0 ;added values from R7 and R6
mov r9,#0 ;grandTotal
verifyOdds:
sub r2, r2, #2
cmp r2,#2
blt errorForOdd
bgt verifyOdds
beq manageArray
errorForOdd:
;It's odd, so we skip calculating, because we never hit 2
mov r0,#1
ldr r1,=oddPrompt
swi 0x69
swi 0x11
manageArray:
ldr r2,=array
loop:
;Here, populate and add array elements.
;R2 will be re-purposed for this to conserve space.
swi 0x6d
and r0,r0,#0xff ;get time tick UP to 255 (via hex)
mov r1,r0
mov r0,#1
;swi 0x6b
str r1,[r2],#4
cmp r4,#arrayLength
addlt r4,r4,#1
blt loop ;ORIGINAL 49, now 50
moveq r4,#0
ldreq r2,=array
beq addArray
addArray:
ldrlt r6,[r2,#0] ;element 1
ldrlt r7,[r2,#4] ;element 2
add r2,r2,#8
add r8,r7,r6 ;store to r8
;mov r9,r8
add r9,r8,r9
cmp r4,#arrayLength
addlt r4,r4,#1
blt addArray
beq total
total:
mov r0,#1
ldr r1,=totalPrompt
swi 0x69
mov r1,r9 ;r1 has to hold the total to print
mov r0,#1 ;r0 must be set to true
swi 0x6b ;PRINT TOTAL NOW
swi 0x11
terminate:
mov r0,#1
ldr r1,=terminatedPrompt
swi 0x69
swi 0x11

Resources