0
votes

I'm working with arduino board. I'm coding in C but I want to use inline assembly.i have this code:

volatile int input1[20]={1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,4};
volatile   int input2[20]={1,2,8,9,6,2,0,3,4,5,6,7,0,0,0,2,2,3,3,0};
volatile   int temp[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
volatile int output[40]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//  // put your main code here, to run repeatedly:
 void setup() {

 // put your setup code here, to run once:
 Serial.begin(9600);


}

void loop() {
 asm(

"statrt:;"
"ldi   YL, low(input1[0]) ;   " //load address of Data
"ldi   YH, high(input1[0]) ;  "
"ldi   ZL, low(input2[0])   ; " //load address of Data
"ldi   ZH, high(input2[0])   ;"
"CompareLoop:;"
"lpm r0 , Z+;"
"lpm r1 , Y+;"
"cp r1,r0;"
"brlt Change;"
"cpi Z,20;"
"breq SubLoop;"
"brne CompareLoop;"

"Change:"
"lds   XL, low(temp[0])    ;" //load address of Data
"lds   XH, high(temp[0])   ;"
"MoveToTempLoop:"
"lpm r3,Z+;"
"st temp+,r3;"
"cpi Z,20;"
 "brne MoveToTempLoop;"

 "MoveToInput1Loop:"
 "lpm r3,Y+;"
 "st Z+,r3;"
 "cpi Z,20;"
 "brne MoveToInput1Loop;"

 "MoveToInput2Loop:"
 "lpm r3,temp+;"
 "st Y+,r3;"
 "cpi Y,20;"
 "brne MoveToInput2Loop;"
 "statrt:;"
 "add r3,r3;"
 "lds   XL, low(output[39])    ;" //load address of Data
 "lds   XH, high(output[39])   ;"

 "lds   YL, low(input1[19])    ;" //load address of Data
 "lds   YH, high(input1[19])   ;"

 "lds   ZL, low(input2[19])    ;" //load address of Data
 "lds   ZH, high(input2[19])   ;"
 "SubLoop:"
 "clr r2;"
 "lpm r0 , Z-;"
 "lpm r1 , Y-;"
 "cp r1,r0;"  //check kon moghe r1-r0 r1 koochiktar nabashe
 "brge Label;"
 "lpm r2,Z;"
 "subi r2,1;"
 "add r1,10;"
 "st Z,r2;"

 "Label:"
 "sub r1,r0;"
 "st X-,r1;"
 "cpi    ZL, -1 ;"      //if i >-1 then
 "brne    SubLoop ;"      // do it again

 );
 int i=0;
 for ( i=0; i<40;i++){
  Serial.println(output[i]);
}
}

actually I have 2 big number that have 20 digits and I want to have input1-input2. but the answer is 0 always :( it seams that it never executes the asm part ...

1
Are you sure your volatile data is in program memory? Also, use a debugger to step through the code and see where it goes wrong.Jester
actually i don't really know what does the lpm do! and I don't know what is in program memory. actually i'm beginner in using arduino and coding with avr...niloofar latifian
And your question is? How to write assembly which will produce input1-input2? Well, first you need to learn to program in assembly.. and after few weeks of learning and practice come back to this and do it.Ped7g
i worked with MIPS so and i know programming MIPS but i worked a little with avr. and actually i think the problem is with lds and lpm but i don't really know what they do.niloofar latifian
Consult an instruction set reference (that's what you did for MIPS too, right?) Note that avr is harvard architecture so has separate data and code memory. lds loads from the former, lpm from the latter.Jester

1 Answers

1
votes

This code has many problems:

Firstly, you need to put \n\t (or just \n) at the end of each line of assembly, otherwise it gets squished into one big line. In your case this means everything but the first instruction ends up as a comment.

Secondly, as you're using C-style comments, you don't actually need the semicolons in the assembly code. Assembly semicolons are only used for comments, they aren't necessary to end the instruction.

Thirdly, you are trying to access C variables from within the assembly code - you can't do this, you have to assign them to registers using the input and output sections (which you don't currently have).

Lastly, you are using asm instead of asm volatile which can cause issues in some circumstances.


In summary, I think you should re-read GCC's explanation of basic assembly and extended assembly to make sure you understand how your assembly code is supposed to be structured.

Also refer to an AVR instruction set reference to make sure you know what the instructions are doing (such as lpm).