1

Just had the first lesson on Assembly at class today. The lecturer didnt explain much as the idea was we have to use books to read up how assembly works. My programming background is Python and C++ and comming to assembly it somehow feels sacrilege to even consider of jumping back and forth into the code.

When talking about branching a problem keeps bothering me that doesnt seem to be explained anywhere in my book. Basically the OP-code B+(EQ,PL,etc) does branches according to the conditions and flags. For example "BEQ location" would branch to "location" if....that is, if what. From what i been able to make out, it uses the previous instuction to figure out the condition (in this case if something is equal (Z=1)). If its true that BEQ would look at the return of previous instrucion to evaluate EQ, how can i, for example, make a loop where first R0(register 0) gets value 0, and later something else happens and at the end i wana make a conditional branch that checks if R0 is zero?

Question 2: I noticed also that if you are making some kind of function:

WhileLoop:
     MOV R0, R1
     ..bla bla bla
     BEQ WhileLoop

How do i know that BEQ goes back to "WhileLoop"? Does this mean that for every function i make i need to call it something different. Maybe i dont understand functions correctly.

Please help.

TomatoLV
  • 67
  • 1
  • 6
  • 3
    1) the flags are bits in the program status register. They are not necessarily set by the directly preceding instruction. See also the [`s` suffix](http://infocenter.arm.com/help/topic/com.arm.doc.dui0801e/pge1424433173696.html) 2) yes, global labels need to be unique. Your assembler might support some form of locals labels. – Jester Sep 11 '18 at 18:20
  • re: structured programming in assembly: as long as you write loops and branches that correspond to high-level structured programming, you can keep things simple and not spaghetti code. See [Where did the notion of "one return only" come from?](https://softwareengineering.stackexchange.com/q/118703) for more insight into the kind of messes that structured programming rules like no GOTO were trying to avoid. – Peter Cordes Sep 11 '18 at 18:49
  • You can even put comments like `@ do {` and `@ } while(condition)` in your asm to keep track of what kind of structured loop or if() construct you're implementing with your branches. See [Why are loops always compiled into "do...while" style (tail jump)?](https://stackoverflow.com/q/47783926) for examples of commenting simple loops. (x86, but the idea works identically in ARM.) – Peter Cordes Sep 11 '18 at 18:50
  • 1
    the CPU itself has limited amount of cells holding 0/1 information = the "registers", program counter, status register (sometimes called "flags") and everything else is stored in these cells, so knowing the full content of them at specific moment can fully describe "state" of CPU. And CPU is like finite-state machine automata, i.e. for every previous state there is fixed outcome of next state after next "machine cycle", although here comes into play also state/content of connected memory (and I/O bus on some architectures, but ARM has only memory mapped I/O IIRC(?)). It's that simple ;) ... – Ped7g Sep 11 '18 at 19:24
  • 1
    so jumping back and forth in the code (or even into the middle of code on architectures where instructions are of variable length and there is no alignment requirement for program counter) is of no problem to the CPU itself. It may be problematic for the assembly source author/maintainer/reviewer, but CPU itself just switch from one state to next one at every machine cycle, not worried at all how your original source did look, happily executing whatever nonsense you throw at it, including running through data and interpreting them as code and similar common mistakes... – Ped7g Sep 11 '18 at 19:27

1 Answers1

1

You need to read the ARM documentation. The answers to your questions are there.

Yes ARM uses flags. As with any instruction set that uses flags you need to examine each instruction you are using or wish to use or for general understanding to see what if any flags they modify. For example an AND operation does it make sense to set the carry flag? Nope, but does it make sense to set the zero flag? Sure it could be useful, or sometimes they TST sets the zero flag but AND doesnt, depends on architecture.

Unlike your typical flag basd solution, ARM for a while there had a twist, you have to ASK the instruction to set the flags. If you notice

loop:
  sub r0,#1
  bne loop

does not do what you want it to do because as written (per the arm docs) the subtract dos NOT touch any flags in particular the Z flag we are testing, but...

loop:
  subs r0,#1
  bne loop

This code, the subtract DOES touch the Z flag.

It allows for things like

  cmp r2,r3
  moveq r1,#1
  bxeq lr
  mov r1,#0
  bx lr

Or say

  if(foo==1)
  {
     bar++;
  }

you normally would need to implement that as

compare with 1
branch if not equal to skip
increment
skip:

so you have a pipe and maybe fetch hit with the branch

but instead

compare with 1
increment if equal

conditional execution, the condition bits.

Now thats for full sized arm instructions, the thumb instructions are a different story.

And with the 64 bit instruction set aarch64 this whole conditional thing went away, four bits being burned every instruction for conditional execution is a bit painful, not used enough. They could have had 32 general purpose registers instead that might have been more useful...

So not sure what you are asking about functions, first off in assembly language you can often use labels like WhileLoop. The assembler turns that into the right instrution, WhileLoop is not an instruction it is basically an address, in this case the assembler should use the instruction you asked for and do a pc relative offset (the fixed address is not used, it counts up how many instructions between the label and the beq and says if equal branch backward N instructions). if you put a beq to some label and that is defined in another module/object the linker will then have to patch up the instruction later.

As far as functions, so if writing a program in C and I want to make several instructions do I need to make all the function names different? Yep. There is really no such thing as a function in assembly, there are some directives to give the illusion of one, but its just a fancy label. But the code that represents a function, if you want to write 7 of them yes you need to use different labels for each. Assembly language has nothing to do with it.

gnu assembler has an interesting feature which there is no reason to assume other assembly languages support (asssembly language is defined by the assembler, the tool, NOT the target (ARM instruction set)), very easy to demonstrate this for many different instruction sets, easy to write arm assembly that does not assemble across all the actively supported assemblers out there. So here is a gnu assembler trick that may or may not help you with labels

1:
 subs r0,#1
 beq 1f
 b 1b
1:

You normally would want to just do the bne but this demonstrates the feature. a label that is a number is special 1f means label 1: forward so the next label 1: down the page. 1b means 1: backward so from that point read backward up the page to find the next 1: so you dont have to do

myfunction:
...
myfunction00:
...
myfunction01:
...
myfunction02:
...

because you are struggling to make intermediate labels to deal with simple branches over stuff and loops.

You can choose whether it is a feature or a burden because it creates a habit that may or may not be tool specific.

old_timer
  • 69,149
  • 8
  • 89
  • 168