I have a small question about using ASM in c. I want to execute the instruction:
LDR PC,=0x123456
This gives me the error "unexpected token in operand".
asm("LDR PC,=0x123456");
This gives "invalid constraint".
asm("LDR PC," : "m" (0x123456));
What's the right way to do this?
You are using this:
asm("LDR PC,=0x123456");
This is not a standard ARM assembly instruction, but a pseudo-instruction provided as a compiler extension. This pseudo-instruction is converted to other assembly instructions when you compile it. It seems clang doesn't support this compiler extension (see this thread). You should do the conversion to assembly instructions yourself, see the ARM documentation for how the LDR pseudo-instruction is converted.
You can probably achieve the effect you want in plain C:
((void (*)(void))0x123456)();
or if you prefer more verbose:
typedef void FN(void);
((FN*)0x123456)();
I agree with #Étienne. I tried you code with mi Google toolchain. It's working fine.
I think you should read the manual how the compiler changes the directive to instructions (normally two mov instructions).
Related
I was wondering what the actual meaning of # zero_extendqisi2 in gcc assembly output was and also the usage. I couldn't find what qisi stands for or anything along those lines.
For context, the line is ldrb r3, [fp, #-9] # zero_extendqisi2 and this is ARM on a Raspberry Pi Zero W, compiled with GCC. For example, when reloading an unsigned char with conversion to int, with optimization disabled, with GCC9.2 with no options. https://godbolt.org/z/7xnfqh. Older GCC all the way to the earliest on Godbolt (4.5) and presumably earlier print the same comment.
This is an RTL instruction name, included in the Standard Names list of the GCC internals manual under zero_extendmn2. Here m,n are the machine modes qi and si, which are respectively a byte and a 32-bit integer. So this is GCC's indication that it is generating an instruction which takes a byte (here loaded from memory) and zero-extends it into a 32-bit integer (here in the register r3). Which is exactly what the ARM ldrb instruction does.
I don't know what the 2 stands for, but it's apparently part of GCC's naming convention.
As Peter points out, it's a little odd that GCC would include such a comment in the assembly without -fverbose-asm. Indeed the comment is coded in as part of the template string in the machine description file, arm.md. It could have been a debugging aid that some GCC developer added and then forgot to take out.
(If you submit this for your assignment, please cite this post properly.)
I'm building legacy code using the GNUARM C compiler and trying to resolve all the implicit declarations of functions.
I've come across some ARM specific functions and can't find the header file containing the declarations for these functions:
get_pc
get_cpsr
get_sp
I have searched the web and only came up with source code containing these functions without any non-standard include files.
I'll also settle for the function declarations.
Since I will also be porting the code to the Cygwin / Windows platform, what are the equivalent declarations for Cygwin GNU GCC?
Thanks.
Just write your own if you really need those functions, asm is easier than inline asm:
.globl get_pc
get_pc:
mov r0,pc
bx lr
.globl get_sp
get_sp:
mov r0,sp
bx lr
.globl get_cpsr
get_cpsr:
mrs r0,cpsr
bx lr
At least for arm. if you are porting to x86 and need the equivalents, I have to wonder what the code needs with those things anyway. the cpsr in particular you would likely have to change any code that uses the result as the status registers across processor vendors/families pretty much never match. The x86 equivalents should still be about the same level of effort, takes longer to do a google search and read the results than it is to just write the code (if you know the processor).
Depending on what your application is doing it is probably better to just comment out any code that calls those functions and/or uses the return value. I can imagine a few reasons why those items would be used, but it could get into architecture specific stuff and that is more involved than just porting a few register read functions. So what user786653 asked is the key question. How are these functions used? Not where can I find them but how are they used and why do you think you need them.
Are you sure those are functions? I'm not very familiar with ARM, but those sound like compiler intrinsics to me. If you're moving to GCC, you might be better off replacing those with inline assembly.
How can I use external defines such as LONG_MIN and LONG_MAX in ARM assembler code?
Let's say my_arm.h looks like this:
int my_arm(int foo);
Let's say I have a my_main.c as follows:
...
#include <limits.h>
#include "my_arm.h"
...
int main (int argc, char *argv[])
{
int foo=0;
...
printf("My arm assembler function returns (%d)\n", my_arm(foo));
...
}
And my_arm.s looks like this:
.text
.align 2
.global my_arm
.type my_arm, %function
my_arm:
...
ADDS r1, r1, r2
BVS overflow
...
overflow:
LDR r0, LONG_MAX # this is probably wrong, how to do it correctly?
BX lr # return with max value
The second to last line, I am not sure how to load correctly, I vaguely remember reading somewhere, that I had to define LONG_MAX in .global, but can't find the link to a working example anymore.
I am compiling with arm-linux-gnueabi-gcc version 4.3.2
==================
UPDATE: Appreciate the suggestions! Unfortunately, I am still having trouble with syntax.
First, I made a little header file mylimits.h (for now in same dir as .S)
#define MY_LONG_MIN 0x80000000
in my_arm.S i added the following:
...
.include "mylimits.h"
...
ldr r7, =MY_LONG_MIN # when it was working it was ldr r7, =0x80000000
...
Two problems with this approach.
First the biggest problem: the symbol MY_LONG_MIN is not recognized...so something is still not right
Second: syntax for .include does not let me include <limits.h>, I would have to add that in mylimits.h, seems a bit kludgy, but I suppose, that is ok :)
Any pointers?
I have access to ARM System Developer’s Guide Designing and Optimizing System Software[2004] and ARM Architecture
Reference Manual[2000], my target is XScale-IXP42x Family rev 2 (v5l) though.
Often the lowercase file extension .s implies that assembler should not be passed through the c preprocessor, whereas the uppercase extension .S implies that it should.
It's up to your compiler to follow this convention though (gcc ports normally do), so check its documentation.
(EDIT: note that this means you can use #include directives - but remember that most of the files you would include would not normally be valid assembler (unless they consist entirely of #defineitions), so you may have to write your own header that is)
edit 5 years later:
Note that the armcc v5 compiler follows this behaviour under linux... but not on windows.
If you are using gcc and its assembler, it is straightforward: name the file with final .S, then add at the beginning #include <limits.h> and use wherever you need the constant, e.g. ldr r0, SOMETHING; I did tests with x86 since it is what I have, but the same works since it is a gcc feature.
What I ended up doing is this:
in my_main.c
#include <limits.h>
...
int my_LONG_MAX=LONG_MAX;
then in my_arm.S
ldr r8, =my_LONG_MAX
ldr r10, [r8]
It looks convuluted and it is(plus the portability gains are questionable in this approach).
There must be a way to access LONG_MAX directly in assembly. Such a way I would gladly accept as the full answer.
I have seen simply feeding gcc the assembler source vs gas will allow you to do C like things in assembler. It is actually a bit scary when you come across situations where you must use gcc as a front end to gas to get something to work, but that is another story.
use --cpreproc for armasm option and add
#include "my_arm.h"
into my_arm.s.
it works for Keil ARM
Silly question, but I just can not find the necessary flag in gcc. Basically, I have in my C program the following inline assembler code
__asm__ __volatile__ ("lea ebx, [timings] \n\t");
When compiling, I get an errormessage which says: Error: invalid char '[' beginning operand 2[timings]'`
Now I remember that a long time ago I used some kind of flag that told the compiler that it is x86 inline assembly. But cant find it online, could maybe someone please tell me which flag i have to use?
Thank you so much!
You can't specify variables that way with GCC. See this document for a detailed description of how to use inline assembler. Also, keep in mind that GCC uses AT&T syntax, not Intel syntax, so you have to put your destinations on the right.
Try using __asm__ instead. Look here for more.
Also, try removing the \n\t from inside the assembly code.
i am designing a compiler in c . but for certain problems like big integers i have to code in assembly code . so how can i integrate assembly code in c?
i am wrting my code in dev cpp.. which i suppose uses gcc ... in windows..!!..
pls give me instructions for linux too
using asm
Good article : GCC-Inline-Assembly-HOWTO
Use the 'asm' instruction, e.g.
asm("movl %ecx %eax"); /* moves the contents of ecx to eax */
Don't you compile the runtime with your own compiler?
Note that another option is to use an external assembler (like AS). Less optimal, but the principle is portable. (though assembler syntaxes vary wildly)
Our own little compiler (which is GCC linking compatible) used AS for most of its assembler, and only acquired an own internal assembler after 8 year or so.
P.s. if you implement an internal assembler, have a look at NASM, their tables of assembler instructions and their addressing are really clean and can be often get converted (and used for regular updates for new instructions)