Code generated for Teensy40

Status
Not open for further replies.

ossi

Well-known member
I want to get an insight into the code that is generated by the compiler. Since I am quite new to ARM assembly code I have some questions. I compile the following (nosense) test-program on the Teensy40:

Code:
volatile int a,b,c ;
volatile int kStop ;
 
void setup() {
  Serial.begin(9600);
  delay(1000) ;  
  Serial.print("Hello teensy40armDisasm0\n"); 
  kStop=0 ;
  while(1){
    a=a+0x1234 ;
    b=a+0x5678 ;
    xstop() ;
    }
  Serial.print("end setup....\n"); 
  }

void xstop(){
  Serial.printf("a=%08XH b=%08XH\n",a,b) ;
  kStop++ ;
  if(kStop>3){ 
    while(1){} ;
    }
  }
    
void loop(){
  }

The code generated is:
Code:
void setup() {
      b4:	b508      	push	{r3, lr}
  Serial.begin(9600);
  delay(1000) ;  
      b6:	f44f 707a 	mov.w	r0, #1000	; 0x3e8
      ba:	4c0c      	ldr	r4, [pc, #48]	; (ec <setup+0x38>)
      bc:	f000 f838 	bl	130 <delay>
        virtual int read() { return usb_serial_getchar(); }
        virtual int peek() { return usb_serial_peekchar(); }
        virtual void flush() { usb_serial_flush_output(); }  // TODO: actually wait for data to leave USB...
        virtual void clear(void) { usb_serial_flush_input(); }
        virtual size_t write(uint8_t c) { return usb_serial_putchar(c); }
        virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial_write(buffer, size); }
      c0:	480b2119 	.word	0x480b2119
      c4:	f000 ffbe 	bl	1044 <usb_serial_write>
      c8:	4b0b4d0a 	.word	0x4b0b4d0a
  Serial.print("Hello teensy40armDisasm0\n"); 
  kStop=0 ;
      cc:	2200      	movs	r2, #0
      ce:	601a      	.short	0x601a
  while(1){
    a=a+0x1234 ;
      d0:	6821      	ldr	r1, [r4, #0]
      d2:	f241      	.short	0xf241
      d4:	2234      	movs	r2, #52	; 0x34
    b=a+0x5678 ;
      d6:	f245      	.short	0xf245
      d8:	6378      	str	r0, [r7, #52]	; 0x34
  Serial.begin(9600);
  delay(1000) ;  
  Serial.print("Hello teensy40armDisasm0\n"); 
  kStop=0 ;
  while(1){
    a=a+0x1234 ;
      da:	440a      	.short	0x440a
      dc:	6022      	str	r2, [r4, #0]
    b=a+0x5678 ;
      de:	6822      	.short	0x6822
      e0:	4413      	add	r3, r2
      e2:	602b      	.short	0x602b
    xstop() ;
      e4:	f7ff ffca 	bl	7c <xstop()>
      e8:	bf00e7f2 	.word	0xbf00e7f2
      ec:	0ddc      	lsrs	r4, r3, #23
      ee:	2000      	.short	0x2000
      f0:	0014      	movs	r4, r2
      f2:	2000      	movs	r0, #0
      f4:	20000de0 	.word	0x20000de0
      f8:	0de4      	lsrs	r4, r4, #23
      fa:	2000      	movs	r0, #0

000000fc <loop>:
  if(kStop>3){ 
    while(1){} ;
    }
  }
    
void loop(){
      fc:	bf004770 	.word	0xbf004770

I have the following questions: What is the purpose of the code generated by the many .short directives? Why does the source-code appear two times in the assembly listing? Is the code generated two times? If so, why?
 
I've seen this too a few times. I'm pretty sure something is buggy or wrongly configured with the arm-none-eabi-objdump we're using to create the .lst file.

Maybe try getting a newer copy and run it to turn the .elf into a new .lst file. Please let me know if you see the same wrong result, or if it gives better assembly listing.
 
I have downloaded and executed the toolchain-install-exe. That did not change anything: Still the wrong result.
Do I have to make special steps (beside execute of the install file) to install the newest toolchain?
 
Arduino will not automatically use a different toolchain.

In Arduino, use File > Preferences to turn on verbose output while compiling. Then click Verify and when it's done, scroll up to find the command where the .lst file was created from the .elf file. Look for it shortly after "Linking everything together...". The first command after than line runs the linker, then you should see two objcopy commands which create the .hex and .eep files files, then the two objdump commands which create the .lst and .sym files.

Open a terminal (Mac, Linux) or command prompt (Windows) and copy & paste that command. Delete the .lst file and run it once as-is, just to make sure it really does (wrongly) recreate the .lst file.

Then edit the pathname to arm-none-eabi-objdump to wherever you installed the new toolchain. Again, delete the .lst file, then run the command with the new version. Hopefully it will give you a better .lst file?
 
I observed the same problem and since then used the online disassembler https://onlinedisassembler.com/static/home/index.html which generates better output.

However, following Pauls advice I tried objdump from gcc-arm-none-eabi-9-2019-q4 which is working perfectly. (parameters: -d -S --demangle --no-show-raw-insn --syms)
Here the output from a standard blink.

BTW: I also tried to compile with this toolchain. At least the core libraries and the blink code compiled without problem (didn't try anything else so far)

Code:
00000060 <setup>:
#include "Arduino.h"

void setup()
{
  pinMode(LED_BUILTIN,OUTPUT);
      60:	movs	r1, #1
      62:	movs	r0, #13
      64:	b.w	150 <pinMode>

00000068 <loop>:
			return (CORE_PIN13_PINREG & CORE_PIN13_BITMASK) ? 1 : 0;
      68:	ldr	r3, [pc, #36]	; (90 <loop+0x28>)
      6a:	ldr	r2, [r3, #8]
      6c:	tst.w	r2, #8
				CORE_PIN13_PORTCLEAR = CORE_PIN13_BITMASK;
      70:	mov.w	r2, #8
			return (CORE_PIN13_PINREG & CORE_PIN13_BITMASK) ? 1 : 0;
      74:	bne.n	82 <loop+0x1a>
}

void loop()
{
  digitalWriteFast(LED_BUILTIN,!digitalReadFast(LED_BUILTIN));
  delay(500);
      76:	mov.w	r0, #500	; 0x1f4
				CORE_PIN13_PORTSET = CORE_PIN13_BITMASK;
      7a:	str.w	r2, [r3, #132]	; 0x84
      7e:	b.w	94 <delay>
      82:	mov.w	r0, #500	; 0x1f4
				CORE_PIN13_PORTCLEAR = CORE_PIN13_BITMASK;
      86:	str.w	r2, [r3, #136]	; 0x88
      8a:	b.w	94 <delay>
      8e:	nop
      90:	.word	0x42004000
 
I followed Pauls advice and tried objdump from the new toolchain (GNU Tools Arm Embedded\9 2019-q4-major). It seems to work perfectly. So thanks for the advice. Thanks also to luni for the hint to the online disassembler.

A question to luni: Can the online tool be used for the teensy 4.0 ? Wich architecture has to be selected then?
 
Last edited:
Update on the topic of disassembler

I followed Pauls advice and tried objdump from the new toolchain (GNU Tools Arm Embedded\9 2019-q4-major). It seems to work perfectly. So thanks for the advice. Thanks also to luni for the hint to the online disassembler.

A question to luni: Can the online tool be used for the teensy 4.0 ? Wich architecture has to be selected then?

Hi!

I'm totally new to Teensy, (ordered a T 4.1 yesterday), VCS and platform IO.
I would like an update on the best tool for disassembler, and the best tool/extension to integrate it in VSC IDE.
So far I have installed the compiler explorer extension.

I love to write CPU-intensive algorithms in assembler, more efficient than the C compiler, and I will probably need all MIPS and FLOPS available in my little teensy :)
 
Status
Not open for further replies.
Back
Top