It looks like it assumes it has access to the standard C libraries in some manner, I assume a linker command about which you said nothing.
I can see it is supposed to print a display message, take 3 numbers from a user and add them up and display result all using the standard C calls.
None of which will work in baremetal so you must be in a linux command window.

It looks like it assumes it has access to the standard C libraries in some manner, I assume a linker command about which you said nothing.
I can see it is supposed to print a display message, take 3 numbers from a user and add them up and display result all using the standard C calls.
None of which will work in baremetal so you must be in a linux command window.

So what does it do?

Sorry you are right I totally forgot. Okay so this program is done in assembly language it’s supposed to output the sum of three numbers but for example input: “1, 2, 3” I get the result of “ you entered 1, 2, 3 and the sum is 1993959032” I’m not sure where the problem is

They were the right way around to start with. Initially R4 holds the address of the first variable but it needs to be copied to R1 for the scanf call, same for the R5 and R6.

What looks to be wrong is the result (sum) which is in R7 at the end needs to be pushed onto the stack otherwise the printf call will use whatever random value is on the top of the stack as the sum. (Assuming normal AAPCS rules, R0 to R3 for the first four parameters then any more have to be pushed on to the stack).

The code has unnecessary instructions where you load a value into a register just to move it into another,

I do not see a declaration for scanf or printf as externs, both of which your code calls.

Also please avoid fake names like pop no such instruction in 32-bit ARM. Also what are you poping off of the stack to start with? To return from your function you jsut need to move lr (R14) into pc (r15) so you end up using a MOV R15, R14 instruction to return.

RPi = Way for me to have fun and save power.
100% Off Grid.
Household TTL Electricity Usage = 1.4KW/h per day.
500W Solar System, produces 2.8KW/h per day average.

Ok I saw you saved the lr on the stack. Do stack ops using the actual instructions (usually LDMFD and STMFD), it will make your code more readable than using a faked op like POP that does not actually exist in the instruction set (and I would bet is implemented as LDMFD).

RPi = Way for me to have fun and save power.
100% Off Grid.
Household TTL Electricity Usage = 1.4KW/h per day.
500W Solar System, produces 2.8KW/h per day average.

Ok I saw you saved the lr on the stack. Do stack ops using the actual instructions (usually LDMFD and STMFD), it will make your code more readable than using a faked op like POP that does not actually exist in the instruction set (and I would bet is implemented as LDMFD).

Push and pop do exist in the instruction set - they are real 16-bit instructions in T32 (thumb2).
Please see page F5.1.138 in the ARMv8 ARM.
They are also, as you say, aliases in A32, as are VPUSH/VPOP.

The idea behind this is that the same assembler code works for thumb2 and for normal ARM.
If you use LDMFD/STMFD it will not work in thumb2 mode.
If you use push and pop, your code will work in both modes.

Quite a lot of ARM instructions are aliases.
There is, surprisingly, no multiply instruction for aarch64. Instead the multiply-add combined instruction (same as "mla" in A32) is used.
So MUL is an alias for MADD rd,rn,rm,xzr (or wzr. Adding from the zero register has no effect of course).

Finally, I think it is a matter of personal opinion which is the most readable. I bet a poll would show the official ARM push/pop is preferred by more people.

Ok I saw you saved the lr on the stack. Do stack ops using the actual instructions (usually LDMFD and STMFD), it will make your code more readable than using a faked op like POP that does not actually exist in the instruction set (and I would bet is implemented as LDMFD).

Push and pop do exist in the instruction set - they are real 16-bit instructions in T32 (thumb2).
Please see page F5.1.138 in the ARMv8 ARM.
They are also, as you say, aliases in A32, as are VPUSH/VPOP.

The idea behind this is that the same assembler code works for thumb2 and for normal ARM.
If you use LDMFD/STMFD it will not work in thumb2 mode.
If you use push and pop, your code will work in both modes.

Quite a lot of ARM instructions are aliases.
There is, surprisingly, no multiply instruction for aarch64. There is instead a multiply-add combined instruction (same as "mla" in A32). So MUL is an alias for MADD rd,rn,rm,xzr (or wzr. Adding from the zero register has no effect of course).

LOL
The combined add and multiply has been there ever since the ARMv2 way back in 1985, and is still there in 32-bit ARM (what some now call AARCH32). It is called MLA.

I did not realize that it was supposed to be thumb code, I thought it was ARM code (yes they run on the same CPU, still a distenction). For ARM code aliases make code less readable, the output of a compiler is not supposed to be easily human readable.

So you are a fan of the APCS convention for register naming? I never liked it because it does not highlight that all the registers are accessable, including R15/PC and R14/LR. Though I also was using ARM before that really caught on. For you if you use APCS reg names, they are (traditional name on let, APCS name on right):

And this also promotes using ONLY R13 for the stack (usefull for a calling convention, though limiting otherwise). There is no good reason not to have multiple stacks (in fact there are good reasons to have multiple stacks). And stack ops in ARM mode work equally well with any base register.

RPi = Way for me to have fun and save power.
100% Off Grid.
Household TTL Electricity Usage = 1.4KW/h per day.
500W Solar System, produces 2.8KW/h per day average.

So you are a fan of the APCS convention for register naming? I never liked it because it does not highlight that all the registers are accessable, including R15/PC and R14/LR. Though I also was using ARM before that really caught on. For you if you use APCS reg names, they are (traditional name on let, APCS name on right):

That's very interesting.
UAL seems to be a mixture: r1 r2 r3 etc, then it uses ip, sp, lr and pc.
I prefer r1, r2, r3 etc for the general purpose registers (much nicer than aarch64 with its x1, x2, x3 (or w1, w2, s3)).
But I like pc, lr, sp because the reader can easily see what they do.
I don't like "ip" which I thought should mean "Instruction Pointer" same as the PC
Compilers don't use frame pointers any more - it free's up a register.

I did not realize that it was supposed to be thumb code, I thought it was ARM code (yes they run on the same CPU, still a distenction). For ARM code aliases make code less readable, the output of a compiler is not supposed to be easily human readable.

Ok I saw you saved the lr on the stack. Do stack ops using the actual instructions (usually LDMFD and STMFD), it will make your code more readable than using a faked op like POP that does not actually exist in the instruction set (and I would bet is implemented as LDMFD).

Push and pop do exist in the instruction set - they are real 16-bit instructions in T32 (thumb2).
Please see page F5.1.138 in the ARMv8 ARM.
They are also, as you say, aliases in A32, as are VPUSH/VPOP.

As jahboater says, PUSH and POP are instructions. Ever since ARM brought in UAL (Unified Assember Language) to replace the individual ARM and THUMB assembler languages back in 2012-ish they have been the recommended instructions to use.

To quote directly from Arm's documentation (2010-2013) :-

The PUSH and POP instructions assume a full descending stack. They are the preferred synonyms for STMDB and LDM with writeback.

So you are a fan of the APCS convention for register naming? I never liked it because it does not highlight that all the registers are accessable, including R15/PC and R14/LR. Though I also was using ARM before that really caught on. For you if you use APCS reg names, they are (traditional name on let, APCS name on right):

That's very interesting.
UAL seems to be a mixture: r1 r2 r3 etc, then it uses ip, sp, lr and pc.
I prefer r1, r2, r3 etc for the general purpose registers (much nicer than aarch64 with its x1, x2, x3 (or w1, w2, s3)).
But I like pc, lr, sp because the reader can easily see what they do.
I don't like "ip" which I thought should mean "Instruction Pointer" same as the PC
Compilers don't use frame pointers any more - it free's up a register.

I did not realize that restricting yourself to calling only R13 the SP is more readable. What if I have code that uses R9 for the stack (which sometimes I do to avoid using the stack pointed to by R13 without having to save the value of R13). In ARM R13 has no special meaning over R0-R12 inclusive. Ok I will admit that I can see the reasoning for giving special names to LR and PC, that is commonly done even pre-APCS.

I did not realize that it was supposed to be thumb code, I thought it was ARM code (yes they run on the same CPU, still a distenction). For ARM code aliases make code less readable, the output of a compiler is not supposed to be easily human readable.

If you have an instruction in one mode and not in another, one of then has to be an alias, there is no choice if you want your code to work in both modes unchanged - which is the whole point of UAL.

Misleading though is it not?

If I am using a call+parameter stack in R9 for example, which is perfectly allowable on ARM, and I attempt to use the PUSH/POP aliases (which do not specify the base register) then I am going to be using the wrong stack.

Just because some things can not be done in thumb16 does not mean we should limit how we do it in ARM.

RPi = Way for me to have fun and save power.
100% Off Grid.
Household TTL Electricity Usage = 1.4KW/h per day.
500W Solar System, produces 2.8KW/h per day average.

I did not realize that restricting yourself to calling only R13 the SP is more readable. What if I have code that uses R9 for the stack (which sometimes I do to avoid using the stack pointed to by R13 without having to save the value of R13).

You can still do that of course. You can implement you own stack with any register you like.

The point is that 99.999% of human programmers and all compilers will use r13 for the stack.
Surely "sp" reads better as "stack pointer" than "r13" does? It does to me anyway.

You wont like aarch64, the stack is accessed as register 31 for some instructions only and is very restricted

Did you know that IBM mainframes had 16 registers and R14 was the link register? I strongly suspect that's where ARM got the idea from!

I think that at very least the OP neads to add the extern directives for printf/scanf as they use both.

Yes, you probably do for some assemblers.
But UAL doesn't appear to need them as far as I can see.

Assembler and command line not specified. I know that they are needed for gas without any extra command line options, they are needed for AsAsm and ObjAsm always, they are needed for Asm, and these are the most commonly used ARM Assemblers (excepting the BASIC assembler, though that is not linkable output).

Thus my responce. I have found that if omited with gas the link symbols are not produced, and the the identifiers are NULL value, which causes a failure. And that ugly barely human readable syntax looks like gas to me.

RPi = Way for me to have fun and save power.
100% Off Grid.
Household TTL Electricity Usage = 1.4KW/h per day.
500W Solar System, produces 2.8KW/h per day average.

I have found that if omited with gas the link symbols are not produced, and the the identifiers are NULL value, which causes a failure. And that ugly barely human readable syntax looks like gas to me.

gas syntax isn't hard to read, maybe if you aren't used to it but horses for courses, saying it's ugly and barely readable is a bit of an overstatement.gas was primarily meant for assembling the output of gcc rather than for use as a standalone assembler anyway.

This assembles with AsAsm on Linux (or RISC OS) and can be linked with ld.

Far from optimal, though in keeping with doing everything the same effective way as the OP, it is pretty decent.

Your "corrected" version is likely to fail, AAPCS says that R0 to R4 are not preserved across a function call (they might be but you cannot expect it) so using the previous values of R1, R2 and R3 after the branches to either puts or scanf is a segfault waiting to happen.

The reason for the OP seeing the wrong sum when printed is because printf was never passed it, sum is the fifth parameter to printf so must be pushed onto the stack. Printf will use whatever it found there, if the caller never pushed it on then whatever value happened to be there will be printed. Your version doesn't push the value on either.

Your "corrected" version is likely to fail, AAPCS says that R0 to R4 are not preserved across a function call (they might be but you cannot expect it) so using the previous values of R1, R2 and R3 after the branches to either puts or scanf is a segfault waiting to happen.

That is the opisite of what APCS says, I am looking at the document as I type this. APCS (which is what is used in RISC OS, and was used in ARM Linux 19 years ago [ok ARM Linux was brand new at the time], and was the standard) says that R1-R3 must be preserved across, while R4-R9 are subject to being overwritten by called procedures. And generally you are safe to use R4 in 99% of cases (experience not the standard).

The reason for the OP seeing the wrong sum when printed is because printf was never passed it, sum is the fifth parameter to printf so must be pushed onto the stack. Printf will use whatever it found there, if the caller never pushed it on then whatever value happened to be there will be printed. Your version doesn't push the value on either.

Interesting change in the standard, making note of it. I will definitely have to look up the newer standard so I can get it correct when talking to Linux/BSD users. I admit I am accustomed to RISC OS, and the way it does things.

I will also double check the errata on APCS as there may have been an error in the original doc, AND going only from memory after my stroke is not always working out.

The AAPCS (yes there are two As, APCS was replaced by ATPCS which was then replaced by AAPCS) has this to say

The first four registers r0-r3 (a1-a4) are used to pass argument values into a subroutine and to return a result value from a function. They may also be used to hold intermediate values within a routine (but, in general, only between subroutine calls).

A subroutine must preserve the contents of the registers r4-r8, r10, r11 and SP (and r9 in PCS variants that designate r9 as v6).

Looking at the APCS info on Arm's website lists r0-r3 as argument / scratch / result and r4-r8 as preserved, that is from 1997/8 so 20 years ago at least. This is what that 1997/8 document said

a1-a4, [f0-f3]
These are used to pass arguments to functions. a1 is also used to return integer results, and f0 to return FP results. These registers can be corrupted by a called function.

v1-v8, [f4-f7]
These are used as register variables. They must be preserved by called functions.

I just looked it up in the APCS erata that I have, and the original doc I have had it reversed. Arguments may be changed by the called procedure (a1-a4 or R0-R3), while variable registers (v1-v6 or R4-R9) must be preserved across calls.

This makes me wonder why the code I posted above assembled linked and ran as expected. Well not so much as none of the three functions called have a good reason to use R0-R3 for internal purposes.

So it works as I demonstrated, though it is by luck of the way the library is coded. As I said memory has not been that great since my medical issue. Sorry for getting that part wrong.

Though if only registers R0 though R3 are used for arguments how is it correctly using the value in R4 for the fifth argument?

RPi = Way for me to have fun and save power.
100% Off Grid.
Household TTL Electricity Usage = 1.4KW/h per day.
500W Solar System, produces 2.8KW/h per day average.

The oldest APCS I could find is from Acorn RISC Machines with a copyright of 1994 (so slightly earlier than I could find on Arm's website), no idea what revision it is though (it doesn't say and it's a plain text document), that has the same usage as now.

No idea on how printf is picking up R4 for you without knowing how it was compiled. Have you tried compiling a C program against it and looking at how it is passing parameters?