AVR gcrt1.S weird call - avr

So basically i have decompiled unoptimized simple program and saw that it runs through gcrt1.S, and i dived in to assembly language and tried to understand what exactly it does. here is my code and my assumption of what it does
00000034 CLR R1 Clear Register
00000035 OUT 0x3F,R1 Out to I/O location
00000036 SER R28 Set Register
00000037 LDI R29,0x08 Load immediate
00000038 OUT 0x3E,R29 Out to I/O location
00000039 OUT 0x3D,R28 Out to I/O location
0000003A CALL 0x00000040 Call subroutine
0000003C JMP 0x00000050 Jump
0000003E JMP 0x00000000 Jump
Clear R1
Clear stratus register
Set R28 1111 1111
Here is where my questions start:
Load R29 from 0x08 (PORTC ?)
OUT to SPH <-R29
OUT to SPL <-R28
Call Main
The confuision that i have is why it loads byte from PORTC register, since the default would be 0x00 anyway
Microcontroller is atmega328p link to a datasheet

Load R29 from 0x08 (PORTC ?)
The instruction is LDI R29,0x08 which loads 8 into R29. LDI is "load immediate to register"; it does not read from memory, see section "31. Instruction Set Summary" in the ATmega328 manual you are using. The code is initializing the frame pointer Y from symbol __stack, see startup code in gcrt1.S.

Related

ARM Cortex M4 SVC_Handler "UsageFault"

I'm creating a context switch program for a personal mini ARM kernel project and the context switch program is written entirely in Assembly. The problem is when I make a SVC call (svc 0) I enter the SVC_Handler but when I try to execute the next instruction I then enter a different handler ("UsageFault_Handler"). The fault occurs before I can pop any of the registers in the SVC_Handler.
Here's a register dump of my gdb screen (right after I enter SVC_Handler and encounter UsageFault_Handler):
(gdb) i r
r0 0x1 1
r1 0x20000bcc 536873932
r2 0x40004404 1073759236
r3 0x1 1
r4 0x0 0
r5 0xc 12
r6 0x3 3
r7 0x20000fe4 536874980
r8 0x1 1
r9 0x0 0
r10 0xb 11
r11 0xa 10
r12 0x2 2
sp 0x2001ffa8 0x2001ffa8
lr 0xfffffff1 4294967281
pc 0x8000188 0x8000188 <UsageFault_Handler>
cpsr 0x3 3
And my context switch:
activate:
cpsie i
/* save kernel state into msp */
mrs ip, msp
push {r4-r11,ip,lr}
/* retrieve routine parameters and switch to the process stack psp */
ldmfd r0!, {ip,lr}
msr control, ip
isb
msr psp, r0
/* software stack frame. load user state */
pop {r4-r11}
/* hardware stack frame. the cpu pops r0-r3, r12 (IP), LR, PC, xPSR automatically */
/* jump to user task*/
bx lr
SVC_Handler:
/* automatically use the msp as the sp when entering handler mode */
/* pop msp stack */
pop {r4-r11,ip,lr}
mov sp, ip
/* back to the thread mode if no other active exception */
bx lr
Not sure what could be causing this problem because I made sure interrupts are enabled and initialized SVC priority to 0x0 (highest priority). Also, I'm using the ARM Cortex M4 STM32F411E evaluation board.
The problem was my interrupt vectors were all even numbers (ARM mode). Attempting to execute instructions when the T bit is 0 (least significant bit of the vector numbers) results in a fault or lockup. Since Cortex-M runs only in Thumb2 state I had to indicate my exception was running in thumb state by placing ".thumb_func" above my interrupt handler in my context-switch assembly.

avr-gdb can not understand my input address

I use simavr and avr-gdb to debug a .hex file, here is the problem:
(gdb) i r pc
pc 0xcd0 0xcd0
(gdb) x/10i 0xc4
0x8000c4: nop
0x8000c6: nop
0x8000c8: nop
0x8000ca: nop
0x8000cc: nop
0x8000ce: nop
0x8000d0: nop
0x8000d2: nop
0x8000d4: nop
0x8000d6: nop
(gdb) x/10i $pc-0xc0c
0xc4: eor r1, r1
0xc6: out 0x3f, r1 ; 63
0xc8: ldi r28, 0xFF ; 255
0xca: ldi r29, 0x08 ; 8
0xcc: out 0x3e, r29 ; 62
0xce: out 0x3d, r28 ; 61
0xd0: ldi r17, 0x05 ; 5
0xd2: ldi r26, 0x00 ; 0
0xd4: ldi r27, 0x01 ; 1
0xd6: ldi r30, 0xEA ; 234
(gdb)
seems that avr-gdb can not understand my input address, and add an offset.
I'm the author of simavr. Sorry I'm not a member of stackoverflow.
The reason you see these addresses is that gdb/gcc do not handle very well architectures that have overlapping 'address space'. The AVR SRAM starts at 0x000, the AVR Flash starts also at 0x000 and the.... eeprom is ALSO considered to be at 0x000 -- this is the 'harvard' architecture.
So, to make gcc/gdb works, everything is compiled in 'virtual address spaces' by adding an arbitrary constant to these offsets -- So the breakdown is that the Flash is considered to be at 0x000 (fine!) the SRAM is considered to be at 0x800000 and the eeprom at 0x810000.
This allows gcc/gdb to be happy -- however the price to pay is that you will see these wierd addressed when debugging, as gdb firmly believe everything is at these offsets.
The best way to handle this is to ... ignore it! There's very little we can do -- I didn't come up with it, it was rolled into avr-gcc long before simavr started in 2009.
You can see the 'address decoder' for simavr addresses there, perhaps it makes things a little bit clearer.
https://github.com/buserror/simavr/blob/4c9efe1fc44b427a4ce1ca8e56e0843c39d0014d/simavr/sim/sim_gdb.c#L357
Hope this help -- if you have further questions, feel free to pop in to freenode #simavr, or even open and 'issue' on github.

LDMIA instruction not working correctly on external SRAM in cortex M4

I am using STM32L486ZG board in thumb mode. I am running a simple bare-metal application without any RTOS. I have external SRAM connected to the board using FSM. The external SRAM is located at address 0x60000000. The system is initialized and running at 72MHz (i have tried this issue with frequency from 18-80 MHz) now in my main function i have following code:
int main(){
asm volatile (
"push {r0}\n"
"mov r0, #0x60000000\n"
"add r0, #0x400\n"
"stmdb r0!, {r1-r12}\n"
"ldmia r0!, {r1-r12}\n"
"pop {r0}\n"
);
}
According to this code no register should be changed after this main function has executed, but that's not the case after the following instruction
ldmia r0!, {r1-r12}
i.e. r9 is not correct after execution. stmdb instruction is working correctly but ldmia is not loading the data correctly. I have verified this by viewing the contents from memory.
This issue is persistent with any arguments in the ldmia instruction: the 9th register is always affected.
Explanation:
Lets say I am debugging this code and the next instruction to execute is this:
stmdb r0!, {r1-r12}
after stepping up all these registers have been saved in the memory and value of r0 is 0x600003d0
the contents of memory:
0x600003D0 00000000 40021008 0000000C .......#....
0x600003DC 40000000 00000000 00000000 ...#........
0x600003E8 20017FEC 00000000 00000000 ì.. ........
0x600003F4 00000000 00000000 00000000 ............
content of the registers:
r0 0x600003d0
r1 0x00000000
r2 0x40021008
r3 0x0000000c
r4 0x40000000
r5 0x00000000
r6 0x00000000
r7 0x20017fec
r8 0x00000000
r9 0x00000000
r10 0x00000000
r11 0x00000000
r12 0x00000000
this shows that all the registers are successfully saved in the memory. Now i step the next instruction
ldmia r0!, {r1-r12}
after this
these are the contents of registers:
r0 0x60000400
r1 0x00000000
r2 0x40021008
r3 0x0000000c
r4 0x40000000
r5 0x00000000
r6 0x00000000
r7 0x20017fec
r8 0x00000000
r9 0x555555d5
r10 0x00000000
r11 0x00000000
r12 0x00000000
as you can see all the registers are restored except r9 which oddly has its value "pop"ed from 0x60000000 instead of 0x600003F0.
Any idea what could be causing this issue. I am using Jlink to write into flash.
P.S. This issue doesn't occur when the registers are saved to onchip SRAM as opposed to external SRAM;
edit
if the instruction
ldmia r0!, {r1-r12}
is split into two parts like:
ldmia r0!, {r1-r6}
ldmia r0!, {r7-r12}
then all the registers are restored successfully
You need to read the STM32L4xx6xx Silicon Limitations. Section 2.2.4 Read burst access of nine words or more is not supported by FMC. ( DocID026121 Rev 4 ) available from ST.
"CPU read burst access equal to or more than 9 registers to FMC returns corrupted data
starting from the 9th read word. These bursts can only be generated by Cortex®-M4 CPU
and not by the other masters (i.e not by DMA).
This issue occurs when the stack is remapped on the external memory on the FMC and
POP operations are performed with 9 or more registers.
This also occurs when LDM/VLDM operations are used with 9 or more registers."

How can I relocate main() to 0x00000000?

Here's the nm dump of my program.
00000000 T __ctors_end
00000000 T __ctors_start
00000000 T __dtors_end
00000000 T __dtors_start
00000000 a __tmp_reg__
00000000 T __trampolines_end
00000000 T __trampolines_start
00000000 T setup
00000001 a __zero_reg__
0000003d a __SP_L__
0000003e a __SP_H__
0000003f a __SREG__
00000072 T __vector_15
00000086 T main
000000a8 A __data_load_end
000000a8 A __data_load_start
000000a8 T _etext
00800100 D _edata
00800100 T _end
00810000 T __eeprom_end
The architecture is AVR, and I need to get main() back up to 0x00000000 in order for the chip that I'm running this code on to execute properly. It should be as simple as a linker script, shouldn't it?
It doesn't matter where main() is in memory. Simply put a jump instruction to its address at the reset vector, or 0x0000 in application memory.
I used to program for AVR and as I know the only way to change main() entry is fuse bits. But you just can to put in the back of FLASH for bootloader. Depending on chip main starts in different places, I'm not sure but on AVR it should be something like 0x20 to 0x100.
It is because at the beginning there is RESET vector, registers and interrupt vectors.
This structure helps very much, once I had a project on which I wasn't able to use watchdog so the only way to trigger reset was overflow.
Also, I've read your comment. You don't need to put 256 bytes of 0x00 that place is for some registers (AVR registers are divided in to places one is SRAM, other FLASH) and interrupt vectors, so if you use lets say timer or UART and your code start at 0x00 so initialization of these would destroy your code.
It is designed to work, I think redesigning would spoil that. But if you really want this, you can try to add -Ttext=0x0000 this flag. This may compile it as you want but I do not recomend doing that.

x86 assember - illegal opcode 0xff /7 under Windows

I'm currently developing an x86 disassembler, and I started disassembling a win32 PE file. Most of the disassembled code looks good, however there are some occurences of the illegal 0xff /7 opcode (/7 means reg=111, 0xff is the opcode group inc/dec/call/callf/jmp/jmpf/push/illegal with operand r/m 16/32). The first guess was, that /7 is the pop instruction, but it is encoded with 0x8f /0. I've checked this against the official Intel Architecture Software Developer’s Manual Volume 2: Instruction Set Reference - so I'm not just missleaded.
Example disassembly: (S0000O0040683a is a lable being jumped to by another instruction)
S0000O0040683a: inc edi ; 0000:0040683a ff c7
test dword ptr [eax+0xff],edi ; 0000:0040683c 85 78 ff
0xff/7 edi ; 0000:0040683f ff ff
BTW: gdb disassembles this equally (except the bug 0xff not yielding -1 in my disassembly):
(gdb) disassemble 0x0040683a 0x00406840
Dump of assembler code from 0x40683a to 0x406840:
0x0040683a: inc %edi
0x0040683c: test %edi,0xffffffff(%eax)
0x0040683f: (bad)
End of assembler dump.
So the question is: Is there any default handler in the illegal opcode exception handler of Windows, which implements any functionality in this illegal opcode, and if yes: What happends there?
Regards, Bodo
After many many additional hours getting my disassembler to produce the output in the exact same syntax than gdb does, I could diff over the two versions. This revealed a rather awkward bug in my disassember: I forgot to take into account, that the 0x0f 0x8x jump instruction have a TWO byte opcode (plus the rel16/32 operand). So each 0x0f 0x8x jump target was off by one leading to code which is not reachable in reality. After fixing this bug, no 0xff/7 opcodes are disassembled any longer.
Thanks go to everyone answering to my question (and commenting that answers as well) and thus at least trying to help me.
Visual Studio disassembles this to the following:
00417000 FF C7 inc edi
00417002 85 78 FF test dword ptr [eax-1],edi
00417005 ?? db ffh
00417006 FF 00 inc dword ptr [eax]
Obviously, a general protection fault happens at 00417002 because eax does not point to anything meaningful, but even if I nop it out (90 90 90) it throws an illegal opcode exception at 00417005 (it does not get handled by the kernel). I'm pretty sure that this is some sort of data and not executable code.
To answer your question, Windows will close the application with the exception code 0xC000001D STATUS_ILLEGAL_INSTRUCTION. The dialog will match the dialog used for any other application crashes, whether it offers a debugger or to send an error report.
Regarding the provided code, it would appear to have either been assembled incorrectly (encoding a greater than 8-bit displacement) or is actually data (as suggested by others already).
It looks like 0xFFFFFFFF has been inserted instead of 0xFF for the test instruction, probably in error?
85 = test r/m32, and 78 is the byte for parameters [eax+disp8], edi, with the disp8 to follow which should just be 0xFF (-1) but as a 32-bit signed integer this is 0xFFFFFFFF.
So I am assuming that you have 85 78 FF FF FF FF where it should be 85 B8 FF FF FF FF for a 32-bit displacement or 85 78 FF for the 8-bit displacement? If this is the case the next byte in the code should be 0xFF...
Of course, as suggested already, this could just be data, and don't forget that data can be stored in PE files and there is no strong guarantee of any particular structure. You can actually insert code or user defined data into some of the MZ or PE header fields if you are agressively optimising to decrease the .exe size.
EDIT: as per the comments below I'd also recommend using an executable where you already know exactly what the expected disassembled code should be.

Resources