Assembly

Understanding the language, error messages, etc.

Assembly

Postby Sorunome » Sun Mar 01, 2015 5:07 pm

I just ordered me a Gamebuino and I was wondering how well assembly compares to the arduino language?
(How does AVR Asm (that is what that thing uses, right?) compare to z80 ASM? (as I'm already familiar with z80 asm))
How well does a mixture of the Arduino language and Asm work?

Did anyone already make any experience with this stuff?

Sorry for question overload, hehe
User avatar
Sorunome
 
Posts: 629
Joined: Sun Mar 01, 2015 1:58 pm

Re: Assembly

Postby NicK » Sun Mar 01, 2015 11:43 pm

I'm interested in doing something with Assembly just for the sake of it. I have recently got heavily into the old ZX Spectrum machine code. I found a very good set of instructional lectures below for ASM:

https://www.youtube.com/watch?v=h8T3PWauYF4

That explains how you can get ASM going for Arduino. There are a few ways it can be incorporated into code (inline assembler) but that is not advised do to the strange syntax.

The problem I would face with a purely ASM code may not be the actual game but in fact all the other parts like the Gamebuino start menu and boot loader. I managed to disassemble a VERY simple pixel routine but it was very long and to my uneducated brain far too complex.

Anyway I continue to try. I know that all this stuff is probably far easier in C and the compiler is probably far better at making the code than I, but for me it's mainly a learning exercise.
NicK
 
Posts: 27
Joined: Tue Dec 23, 2014 11:25 pm

Re: Assembly

Postby Myndale » Mon Mar 02, 2015 7:24 am

I've done quite a bit with Arduino assembly. I don't mind inline asm myself, probably the best introduction would be to search through the entire arduino folder for "__asm__"...plenty of examples in there that can be cross-referenced against a google search for "gcc inline assembly".

As far as learning the op-codes themselves there's a complete list in the Atmet 8-bit AVR Instruction Set Document. It also helps to see the assembly output for C code you write, you can do that by using the objdump utility to convert your ELF files to LST files:

Code: Select all
C:/arduino-1.0.5/hardware/tools/avr/bin/avr-objdump -h -S C:\Users\YOURNAME\AppData\Local\Temp\build123456etc.tmp\yourfile.cpp.elf > output.lst


And then finally there's the Simbuino emulator which doesn't currently support symbols but does let you step through the raw assembly and add breakpoints etc.

Overall the AVR's are much easier to program than most other comparable architectures. The chip does pretty much exactly what you expect it to thanks to no cache lines, multi-stage execution pipelines or branch-prediction to worry about. The main thing to watch out for is the poor shift support; it can only shift one bit at a time, so anything higher has to be implemented as either a loop, look-up table or multiply/divide.
Myndale
 
Posts: 507
Joined: Sat Mar 01, 2014 1:25 am

Re: Assembly

Postby Sorunome » Mon Mar 02, 2015 1:31 pm

NicK wrote:[...]
That explains how you can get ASM going for Arduino. There are a few ways it can be incorporated into code (inline assembler) but that is not advised do to the strange syntax.

The advantage I see with inline ASM is that I could also maybe use some higher level blocks where I don't have to, like, write my own 32bit routines, for example.

NicK wrote:The problem I would face with a purely ASM code may not be the actual game but in fact all the other parts like the Gamebuino start menu and boot loader. I managed to disassemble a VERY simple pixel routine but it was very long and to my uneducated brain far too complex.
[...]

There wouldn't be much to a bootloader, right? As I'd just have custom code interfering with the hardware ports. I mean, the code would just start being executed.


Myndale wrote:[...]
And then finally there's the Simbuino emulator which doesn't currently support symbols but does let you step through the raw assembly and add breakpoints etc.
Too bad that one doesn't exist for linux :(

Myndale wrote:Overall the AVR's are much easier to program than most other comparable architectures. The chip does pretty much exactly what you expect it to thanks to no cache lines, multi-stage execution pipelines or branch-prediction to worry about. The main thing to watch out for is the poor shift support; it can only shift one bit at a time, so anything higher has to be implemented as either a loop, look-up table or multiply/divide.

It's the same with Z80 ASM so I'm used to that ;)


So yeah, thanks for the resources etc.
User avatar
Sorunome
 
Posts: 629
Joined: Sun Mar 01, 2015 1:58 pm

Re: Assembly

Postby jonnection » Mon Mar 02, 2015 2:22 pm

Hi Sorunome

This page got me started on AVR inline assembler:

http://www.nongnu.org/avr-libc/user-manual/inline_asm.html

To learn assembly on the AVR I found it very useful to use avr-objdump like so:

http://rcarduino.blogspot.fi/2012/09/how-to-view-arduino-assembly.html

Then, ofcourse, using Myndale's simulator is one way of stepping through the code. However, it is not your only option. You can code for the Gamebuino on various other toolchains, some of which run native on Linux. You can use GDB and SimulAVR. You can also use Eclipse or Code::Blocks to develop, both have AVR & Arduino plugins/wizards you can use to set up projects easily. You do not have to use the Arduino IDE if you prefer a more advanced toolchain.

http://www.linuxjournal.com/article/7289?page=0,2
User avatar
jonnection
 
Posts: 317
Joined: Sun May 04, 2014 8:21 pm

Re: Assembly

Postby Sorunome » Tue Mar 24, 2015 12:54 pm

Is there somewhere information on how to output things to the screen, so some documentation on how the screen is working on port-level?
Also, I don't quite get it....i have this asm block I want to run (inline) but how can i like populate X Y and Z with existing pointers?

EDIT: Ok, after some debugging i figured that out, i actually set my thingies as output instead of input.

Now, some more intense debugging / decompiling later, it seems that if i do the following times 8 i can output a byte:
Code: Select all
cbi 5,3 ; if bit is supposed to be off then sbi 5,3
sbi 5,5
cbi 5,5


EDIT2: I got another issue now: I have a variable outside of my assembly (one byte) that I want to have in R19 during the asm code and want it to be stored back afterwards. How could I do that?
User avatar
Sorunome
 
Posts: 629
Joined: Sun Mar 01, 2015 1:58 pm

Re: Assembly

Postby Myndale » Wed Mar 25, 2015 3:21 am

Sorunome wrote:Is there somewhere information on how to output things to the screen, so some documentation on how the screen is working on port-level?


Here's the datasheet: https://www.sparkfun.com/datasheets/LCD ... ia5110.pdf
Myndale
 
Posts: 507
Joined: Sat Mar 01, 2014 1:25 am

Re: Assembly

Postby Myndale » Wed Mar 25, 2015 4:09 am

Sorunome wrote:I got another issue now: I have a variable outside of my assembly (one byte) that I want to have in R19 during the asm code and want it to be stored back afterwards. How could I do that?


This isn't quite as straightforward as you might like given that the compiler uses the registers itself to store various variables and pointers. If you change those registers at runtime then the compiled code that depends on them will break. Similarly if the compiler changes registers under your feet then your own code will break too. A good place to start is the gnu compiler documentation for extended assembly:

https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html

Here's some code that shows an example of what you're trying to do, to be safe it disables interrupts while it's running and also saves/restores all variables it uses. It's also important to declare any variables that are shared between compiled code and assembly as volatile so that the code knows their values may change at any time (and thus won't cache them in registers).

Code: Select all
volatile int val = 1;

void setup() {
  Serial.begin(9600);
 
  Serial.print("before: val = ");
  Serial.println(val);
     
  __asm__ __volatile__ (
    "cli                   \n"    // disable interrupts
    "push r19              \n"    // save registers
    "push r28              \n"
    "push r29              \n"
    "ldi r28, lo8(val)     \n"    // load address of val into Y
    "ldi r29, hi8(val)     \n"
    "ld  r19, Y            \n"    // load val
    "inc r19               \n"    // increment
    "st  Y, r19            \n"    // store it back out
    "pop r29               \n"    // restore registers
    "pop r28               \n"
    "pop r19               \n"
    "sei                   \n"    // re-enable interrupts
   );
 
  Serial.print("after: val = ");
  Serial.println(val);
}

void loop() {
}
Myndale
 
Posts: 507
Joined: Sat Mar 01, 2014 1:25 am

Re: Assembly

Postby Sorunome » Wed Mar 25, 2015 10:21 am

Can you do it without having to use one of the pointer register pairs?

To get it into a register I currently have
Code: Select all
asm volatile(
<code that uses %[rotFlagReg] as a register>
::[rotFlagReg] "r" (rotFlagTmp):);
But, well, it doesn't "get out" again.
Also I'm quite positive that gcc already handles the multiple-reg-use-thingy as I'm not allowed to use R1-R15, my code currenlty doesn't break either ^.^
User avatar
Sorunome
 
Posts: 629
Joined: Sun Mar 01, 2015 1:58 pm

Re: Assembly

Postby jonnection » Wed Mar 25, 2015 10:52 am

Hi Sorunome

Did you read the link I posted earlier ? http://www.nongnu.org/avr-libc/user-manual/inline_asm.html

It shows you many different strategies how to interface C with inline ASM. I am not sure what you actually want to do here, but I advise you to read through the page very carefully. It is the single best source of information on this subject I have found so far.

For example, code that swaps bytes of a 32-bit value :
Instead of listing the same operand as both, input and output operand, it can also be declared as a read-write operand. This must be applied to an output operand, and the respective input operand list remains empty:

Code: Select all
asm volatile("mov __tmp_reg__, %A0" "\n\t"
"mov %A0, %D0" "\n\t"
"mov %D0, __tmp_reg__" "\n\t"
"mov __tmp_reg__, %B0" "\n\t"
"mov %B0, %C0" "\n\t"
"mov %C0, __tmp_reg__" "\n\t"
: "+r" (value));
User avatar
jonnection
 
Posts: 317
Joined: Sun May 04, 2014 8:21 pm

Next

Return to Programming Questions

Who is online

Users browsing this forum: No registered users and 20 guests

cron